03575f23260ab7d431664c35c2d05ec72f39d08c
[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 };
82
83 static reloc_howto_type crx_elf_howto_table[] =
84 {
85 HOWTO (R_CRX_NONE, /* type */
86 0, /* rightshift */
87 2, /* size */
88 32, /* bitsize */
89 FALSE, /* pc_relative */
90 0, /* bitpos */
91 complain_overflow_dont,/* complain_on_overflow */
92 bfd_elf_generic_reloc, /* special_function */
93 "R_CRX_NONE", /* name */
94 FALSE, /* partial_inplace */
95 0, /* src_mask */
96 0, /* dst_mask */
97 FALSE), /* pcrel_offset */
98
99 HOWTO (R_CRX_REL4, /* type */
100 1, /* rightshift */
101 0, /* size */
102 4, /* bitsize */
103 TRUE, /* pc_relative */
104 0, /* bitpos */
105 complain_overflow_bitfield,/* complain_on_overflow */
106 bfd_elf_generic_reloc, /* special_function */
107 "R_CRX_REL4", /* name */
108 FALSE, /* partial_inplace */
109 0xf, /* src_mask */
110 0xf, /* dst_mask */
111 FALSE), /* pcrel_offset */
112
113 HOWTO (R_CRX_REL8, /* type */
114 1, /* rightshift */
115 0, /* size */
116 8, /* bitsize */
117 TRUE, /* pc_relative */
118 0, /* bitpos */
119 complain_overflow_bitfield,/* complain_on_overflow */
120 bfd_elf_generic_reloc, /* special_function */
121 "R_CRX_REL8", /* name */
122 FALSE, /* partial_inplace */
123 0xff, /* src_mask */
124 0xff, /* dst_mask */
125 FALSE), /* pcrel_offset */
126
127 HOWTO (R_CRX_REL8_CMP, /* type */
128 1, /* rightshift */
129 0, /* size */
130 8, /* bitsize */
131 TRUE, /* pc_relative */
132 0, /* bitpos */
133 complain_overflow_bitfield,/* complain_on_overflow */
134 bfd_elf_generic_reloc, /* special_function */
135 "R_CRX_REL8_CMP", /* name */
136 FALSE, /* partial_inplace */
137 0xff, /* src_mask */
138 0xff, /* dst_mask */
139 FALSE), /* pcrel_offset */
140
141 HOWTO (R_CRX_REL16, /* type */
142 1, /* rightshift */
143 1, /* size */
144 16, /* bitsize */
145 TRUE, /* pc_relative */
146 0, /* bitpos */
147 complain_overflow_bitfield,/* complain_on_overflow */
148 bfd_elf_generic_reloc, /* special_function */
149 "R_CRX_REL16", /* name */
150 FALSE, /* partial_inplace */
151 0xffff, /* src_mask */
152 0xffff, /* dst_mask */
153 FALSE), /* pcrel_offset */
154
155 HOWTO (R_CRX_REL24, /* type */
156 1, /* rightshift */
157 2, /* size */
158 24, /* bitsize */
159 TRUE, /* pc_relative */
160 0, /* bitpos */
161 complain_overflow_bitfield,/* complain_on_overflow */
162 bfd_elf_generic_reloc, /* special_function */
163 "R_CRX_REL24", /* name */
164 FALSE, /* partial_inplace */
165 0xffffff, /* src_mask */
166 0xffffff, /* dst_mask */
167 FALSE), /* pcrel_offset */
168
169 HOWTO (R_CRX_REL32, /* type */
170 1, /* rightshift */
171 2, /* size */
172 32, /* bitsize */
173 TRUE, /* pc_relative */
174 0, /* bitpos */
175 complain_overflow_bitfield,/* complain_on_overflow */
176 bfd_elf_generic_reloc, /* special_function */
177 "R_CRX_REL32", /* name */
178 FALSE, /* partial_inplace */
179 0xffffffff, /* src_mask */
180 0xffffffff, /* dst_mask */
181 FALSE), /* pcrel_offset */
182
183 HOWTO (R_CRX_REGREL12, /* type */
184 0, /* rightshift */
185 1, /* size */
186 12, /* bitsize */
187 FALSE, /* pc_relative */
188 0, /* bitpos */
189 complain_overflow_bitfield,/* complain_on_overflow */
190 bfd_elf_generic_reloc, /* special_function */
191 "R_CRX_REGREL12", /* name */
192 FALSE, /* partial_inplace */
193 0xfff, /* src_mask */
194 0xfff, /* dst_mask */
195 FALSE), /* pcrel_offset */
196
197 HOWTO (R_CRX_REGREL22, /* type */
198 0, /* rightshift */
199 2, /* size */
200 22, /* bitsize */
201 FALSE, /* pc_relative */
202 0, /* bitpos */
203 complain_overflow_bitfield,/* complain_on_overflow */
204 bfd_elf_generic_reloc, /* special_function */
205 "R_CRX_REGREL22", /* name */
206 FALSE, /* partial_inplace */
207 0x3fffff, /* src_mask */
208 0x3fffff, /* dst_mask */
209 FALSE), /* pcrel_offset */
210
211 HOWTO (R_CRX_REGREL28, /* type */
212 0, /* rightshift */
213 2, /* size */
214 28, /* bitsize */
215 FALSE, /* pc_relative */
216 0, /* bitpos */
217 complain_overflow_bitfield,/* complain_on_overflow */
218 bfd_elf_generic_reloc, /* special_function */
219 "R_CRX_REGREL28", /* name */
220 FALSE, /* partial_inplace */
221 0xfffffff, /* src_mask */
222 0xfffffff, /* dst_mask */
223 FALSE), /* pcrel_offset */
224
225 HOWTO (R_CRX_REGREL32, /* type */
226 0, /* rightshift */
227 2, /* size */
228 32, /* bitsize */
229 FALSE, /* pc_relative */
230 0, /* bitpos */
231 complain_overflow_bitfield,/* complain_on_overflow */
232 bfd_elf_generic_reloc, /* special_function */
233 "R_CRX_REGREL32", /* name */
234 FALSE, /* partial_inplace */
235 0xffffffff, /* src_mask */
236 0xffffffff, /* dst_mask */
237 FALSE), /* pcrel_offset */
238
239 HOWTO (R_CRX_ABS16, /* type */
240 0, /* rightshift */
241 1, /* size */
242 16, /* bitsize */
243 FALSE, /* pc_relative */
244 0, /* bitpos */
245 complain_overflow_bitfield,/* complain_on_overflow */
246 bfd_elf_generic_reloc, /* special_function */
247 "R_CRX_ABS16", /* name */
248 FALSE, /* partial_inplace */
249 0xffff, /* src_mask */
250 0xffff, /* dst_mask */
251 FALSE), /* pcrel_offset */
252
253 HOWTO (R_CRX_ABS32, /* type */
254 0, /* rightshift */
255 2, /* size */
256 32, /* bitsize */
257 FALSE, /* pc_relative */
258 0, /* bitpos */
259 complain_overflow_bitfield,/* complain_on_overflow */
260 bfd_elf_generic_reloc, /* special_function */
261 "R_CRX_ABS32", /* name */
262 FALSE, /* partial_inplace */
263 0xffffffff, /* src_mask */
264 0xffffffff, /* dst_mask */
265 FALSE), /* pcrel_offset */
266
267 HOWTO (R_CRX_NUM8, /* type */
268 0, /* rightshift */
269 0, /* size */
270 8, /* bitsize */
271 FALSE, /* pc_relative */
272 0, /* bitpos */
273 complain_overflow_bitfield,/* complain_on_overflow */
274 bfd_elf_generic_reloc, /* special_function */
275 "R_CRX_NUM8", /* name */
276 FALSE, /* partial_inplace */
277 0xff, /* src_mask */
278 0xff, /* dst_mask */
279 FALSE), /* pcrel_offset */
280
281 HOWTO (R_CRX_NUM16, /* type */
282 0, /* rightshift */
283 1, /* size */
284 16, /* bitsize */
285 FALSE, /* pc_relative */
286 0, /* bitpos */
287 complain_overflow_bitfield,/* complain_on_overflow */
288 bfd_elf_generic_reloc, /* special_function */
289 "R_CRX_NUM16", /* name */
290 FALSE, /* partial_inplace */
291 0xffff, /* src_mask */
292 0xffff, /* dst_mask */
293 FALSE), /* pcrel_offset */
294
295 HOWTO (R_CRX_NUM32, /* type */
296 0, /* rightshift */
297 2, /* size */
298 32, /* bitsize */
299 FALSE, /* pc_relative */
300 0, /* bitpos */
301 complain_overflow_bitfield,/* complain_on_overflow */
302 bfd_elf_generic_reloc, /* special_function */
303 "R_CRX_NUM32", /* name */
304 FALSE, /* partial_inplace */
305 0xffffffff, /* src_mask */
306 0xffffffff, /* dst_mask */
307 FALSE), /* pcrel_offset */
308
309 HOWTO (R_CRX_IMM16, /* type */
310 0, /* rightshift */
311 1, /* size */
312 16, /* bitsize */
313 FALSE, /* pc_relative */
314 0, /* bitpos */
315 complain_overflow_bitfield,/* complain_on_overflow */
316 bfd_elf_generic_reloc, /* special_function */
317 "R_CRX_IMM16", /* name */
318 FALSE, /* partial_inplace */
319 0xffff, /* src_mask */
320 0xffff, /* dst_mask */
321 FALSE), /* pcrel_offset */
322
323 HOWTO (R_CRX_IMM32, /* type */
324 0, /* rightshift */
325 2, /* size */
326 32, /* bitsize */
327 FALSE, /* pc_relative */
328 0, /* bitpos */
329 complain_overflow_bitfield,/* complain_on_overflow */
330 bfd_elf_generic_reloc, /* special_function */
331 "R_CRX_IMM32", /* name */
332 FALSE, /* partial_inplace */
333 0xffffffff, /* src_mask */
334 0xffffffff, /* dst_mask */
335 FALSE) /* pcrel_offset */
336 };
337
338 /* Retrieve a howto ptr using a BFD reloc_code. */
339
340 static reloc_howto_type *
341 elf_crx_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
342 bfd_reloc_code_real_type code)
343 {
344 unsigned int i;
345
346 for (i = 0; i < R_CRX_MAX; i++)
347 if (code == crx_reloc_map[i].bfd_reloc_enum)
348 return &crx_elf_howto_table[crx_reloc_map[i].crx_reloc_type];
349
350 printf ("This relocation Type is not supported -0x%x\n", code);
351 return 0;
352 }
353
354 /* Retrieve a howto ptr using an internal relocation entry. */
355
356 static void
357 elf_crx_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
358 Elf_Internal_Rela *dst)
359 {
360 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
361 BFD_ASSERT (r_type < (unsigned int) R_CRX_MAX);
362 cache_ptr->howto = &crx_elf_howto_table[r_type];
363 }
364
365 /* Perform a relocation as part of a final link. */
366
367 static bfd_reloc_status_type
368 crx_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
369 bfd *output_bfd ATTRIBUTE_UNUSED,
370 asection *input_section, bfd_byte *contents,
371 bfd_vma offset, bfd_vma Rvalue, bfd_vma addend,
372 struct bfd_link_info *info ATTRIBUTE_UNUSED,
373 asection *sec ATTRIBUTE_UNUSED,
374 int is_local ATTRIBUTE_UNUSED)
375 {
376 unsigned short r_type = howto->type;
377 bfd_byte *hit_data = contents + offset;
378 bfd_vma reloc_bits, check;
379
380 switch (r_type)
381 {
382 case R_CRX_IMM16:
383 case R_CRX_IMM32:
384 case R_CRX_ABS16:
385 case R_CRX_ABS32:
386 case R_CRX_REL8_CMP:
387 case R_CRX_REL16:
388 case R_CRX_REL24:
389 case R_CRX_REL32:
390 case R_CRX_REGREL12:
391 case R_CRX_REGREL22:
392 case R_CRX_REGREL28:
393 case R_CRX_REGREL32:
394 /* 'hit_data' is relative to the start of the instruction, not the
395 relocation offset. Advance it to account for the exact offset. */
396 hit_data += 2;
397 break;
398
399 case R_CRX_REL4:
400 /* This relocation type is used only in 'Branch if Equal to 0'
401 instructions and requires special handling. */
402 Rvalue -= 1;
403 break;
404
405 case R_CRX_NONE:
406 return bfd_reloc_ok;
407 break;
408
409 default:
410 break;
411 }
412
413 if (howto->pc_relative)
414 {
415 /* Subtract the address of the section containing the location. */
416 Rvalue -= (input_section->output_section->vma
417 + input_section->output_offset);
418 /* Subtract the position of the location within the section. */
419 Rvalue -= offset;
420 }
421
422 /* Add in supplied addend. */
423 Rvalue += addend;
424
425 /* Complain if the bitfield overflows, whether it is considered
426 as signed or unsigned. */
427 check = Rvalue >> howto->rightshift;
428
429 /* Assumes two's complement. This expression avoids
430 overflow if howto->bitsize is the number of bits in
431 bfd_vma. */
432 reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
433
434 if (((bfd_vma) check & ~reloc_bits) != 0
435 && (((bfd_vma) check & ~reloc_bits)
436 != (-(bfd_vma) 1 & ~reloc_bits)))
437 {
438 /* The above right shift is incorrect for a signed
439 value. See if turning on the upper bits fixes the
440 overflow. */
441 if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
442 {
443 check |= ((bfd_vma) - 1
444 & ~((bfd_vma) - 1
445 >> howto->rightshift));
446 if (((bfd_vma) check & ~reloc_bits)
447 != (-(bfd_vma) 1 & ~reloc_bits))
448 return bfd_reloc_overflow;
449 }
450 else
451 return bfd_reloc_overflow;
452 }
453
454 /* Drop unwanted bits from the value we are relocating to. */
455 Rvalue >>= (bfd_vma) howto->rightshift;
456
457 /* Apply dst_mask to select only relocatable part of the insn. */
458 Rvalue &= howto->dst_mask;
459
460 switch (howto->size)
461 {
462 case 0:
463 if (r_type == R_CRX_REL4)
464 {
465 Rvalue <<= 4;
466 Rvalue |= (bfd_get_8 (input_bfd, hit_data) & 0x0f);
467 }
468
469 bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
470 break;
471
472 case 1:
473 if (r_type == R_CRX_REGREL12)
474 Rvalue |= (bfd_get_16 (input_bfd, hit_data) & 0xf000);
475
476 bfd_put_16 (input_bfd, Rvalue, hit_data);
477 break;
478
479 case 2:
480 if (r_type == R_CRX_REL24
481 || r_type == R_CRX_REGREL22
482 || r_type == R_CRX_REGREL28)
483 Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16) |
484 bfd_get_16 (input_bfd, hit_data + 2)) & ~howto->dst_mask);
485
486 if (r_type == R_CRX_NUM32)
487 /* Relocation on DATA is purely little-endian, that is, for a
488 multi-byte datum, the lowest address in memory contains the
489 little end of the datum, that is, the least significant byte.
490 Therefore we use BFD's byte Putting functions. */
491 bfd_put_32 (input_bfd, Rvalue, hit_data);
492 else
493 /* Relocation on INSTRUCTIONS is different : Instructions are
494 word-addressable, that is, each word itself is arranged according
495 to little-endian convention, whereas the words are arranged with
496 respect to one another in BIG ENDIAN fashion.
497 When there is an immediate value that spans a word boundary, it is
498 split in a big-endian way with respect to the words. */
499 {
500 bfd_put_16 (input_bfd, (Rvalue >> 16) & 0xffff, hit_data);
501 bfd_put_16 (input_bfd, Rvalue & 0xffff, hit_data + 2);
502 }
503 break;
504
505 default:
506 return bfd_reloc_notsupported;
507 }
508
509 return bfd_reloc_ok;
510 }
511
512 /* Delete some bytes from a section while relaxing. */
513
514 static bfd_boolean
515 elf32_crx_relax_delete_bytes (bfd *abfd, asection *sec,
516 bfd_vma addr, int count)
517 {
518 Elf_Internal_Shdr *symtab_hdr;
519 unsigned int sec_shndx;
520 bfd_byte *contents;
521 Elf_Internal_Rela *irel, *irelend;
522 Elf_Internal_Rela *irelalign;
523 bfd_vma toaddr;
524 Elf_Internal_Sym *isym;
525 Elf_Internal_Sym *isymend;
526 struct elf_link_hash_entry **sym_hashes;
527 struct elf_link_hash_entry **end_hashes;
528 unsigned int symcount;
529
530 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
531
532 contents = elf_section_data (sec)->this_hdr.contents;
533
534 /* The deletion must stop at the next ALIGN reloc for an aligment
535 power larger than the number of bytes we are deleting. */
536
537 irelalign = NULL;
538 toaddr = sec->size;
539
540 irel = elf_section_data (sec)->relocs;
541 irelend = irel + sec->reloc_count;
542
543 /* Actually delete the bytes. */
544 memmove (contents + addr, contents + addr + count,
545 (size_t) (toaddr - addr - count));
546 sec->size -= count;
547
548 /* Adjust all the relocs. */
549 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
550 {
551 /* Get the new reloc address. */
552 if ((irel->r_offset > addr
553 && irel->r_offset < toaddr))
554 irel->r_offset -= count;
555 }
556
557 /* Adjust the local symbols defined in this section. */
558 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
559 isym = (Elf_Internal_Sym *) symtab_hdr->contents;
560 for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
561 {
562 if (isym->st_shndx == sec_shndx
563 && isym->st_value > addr
564 && isym->st_value < toaddr)
565 isym->st_value -= count;
566 }
567
568 /* Now adjust the global symbols defined in this section. */
569 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
570 - symtab_hdr->sh_info);
571 sym_hashes = elf_sym_hashes (abfd);
572 end_hashes = sym_hashes + symcount;
573
574 for (; sym_hashes < end_hashes; sym_hashes++)
575 {
576 struct elf_link_hash_entry *sym_hash = *sym_hashes;
577
578 if ((sym_hash->root.type == bfd_link_hash_defined
579 || sym_hash->root.type == bfd_link_hash_defweak)
580 && sym_hash->root.u.def.section == sec
581 && sym_hash->root.u.def.value > addr
582 && sym_hash->root.u.def.value < toaddr)
583 sym_hash->root.u.def.value -= count;
584 }
585
586 return TRUE;
587 }
588
589 /* This is a version of bfd_generic_get_relocated_section_contents
590 which uses elf32_crx_relocate_section. */
591
592 static bfd_byte *
593 elf32_crx_get_relocated_section_contents (bfd *output_bfd,
594 struct bfd_link_info *link_info,
595 struct bfd_link_order *link_order,
596 bfd_byte *data,
597 bfd_boolean relocatable,
598 asymbol **symbols)
599 {
600 Elf_Internal_Shdr *symtab_hdr;
601 asection *input_section = link_order->u.indirect.section;
602 bfd *input_bfd = input_section->owner;
603 asection **sections = NULL;
604 Elf_Internal_Rela *internal_relocs = NULL;
605 Elf_Internal_Sym *isymbuf = NULL;
606
607 /* We only need to handle the case of relaxing, or of having a
608 particular set of section contents, specially. */
609 if (relocatable
610 || elf_section_data (input_section)->this_hdr.contents == NULL)
611 return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
612 link_order, data,
613 relocatable,
614 symbols);
615
616 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
617
618 memcpy (data, elf_section_data (input_section)->this_hdr.contents,
619 (size_t) input_section->size);
620
621 if ((input_section->flags & SEC_RELOC) != 0
622 && input_section->reloc_count > 0)
623 {
624 Elf_Internal_Sym *isym;
625 Elf_Internal_Sym *isymend;
626 asection **secpp;
627 bfd_size_type amt;
628
629 internal_relocs = (_bfd_elf_link_read_relocs
630 (input_bfd, input_section, (PTR) NULL,
631 (Elf_Internal_Rela *) NULL, FALSE));
632 if (internal_relocs == NULL)
633 goto error_return;
634
635 if (symtab_hdr->sh_info != 0)
636 {
637 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
638 if (isymbuf == NULL)
639 isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
640 symtab_hdr->sh_info, 0,
641 NULL, NULL, NULL);
642 if (isymbuf == NULL)
643 goto error_return;
644 }
645
646 amt = symtab_hdr->sh_info;
647 amt *= sizeof (asection *);
648 sections = bfd_malloc (amt);
649 if (sections == NULL && amt != 0)
650 goto error_return;
651
652 isymend = isymbuf + symtab_hdr->sh_info;
653 for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
654 {
655 asection *isec;
656
657 if (isym->st_shndx == SHN_UNDEF)
658 isec = bfd_und_section_ptr;
659 else if (isym->st_shndx == SHN_ABS)
660 isec = bfd_abs_section_ptr;
661 else if (isym->st_shndx == SHN_COMMON)
662 isec = bfd_com_section_ptr;
663 else
664 isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
665
666 *secpp = isec;
667 }
668
669 if (! elf32_crx_relocate_section (output_bfd, link_info, input_bfd,
670 input_section, data, internal_relocs,
671 isymbuf, sections))
672 goto error_return;
673
674 if (sections != NULL)
675 free (sections);
676 if (isymbuf != NULL
677 && symtab_hdr->contents != (unsigned char *) isymbuf)
678 free (isymbuf);
679 if (elf_section_data (input_section)->relocs != internal_relocs)
680 free (internal_relocs);
681 }
682
683 return data;
684
685 error_return:
686 if (sections != NULL)
687 free (sections);
688 if (isymbuf != NULL
689 && symtab_hdr->contents != (unsigned char *) isymbuf)
690 free (isymbuf);
691 if (internal_relocs != NULL
692 && elf_section_data (input_section)->relocs != internal_relocs)
693 free (internal_relocs);
694 return NULL;
695 }
696
697 /* Relocate a CRX ELF section. */
698
699 static bfd_boolean
700 elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
701 bfd *input_bfd, asection *input_section,
702 bfd_byte *contents, Elf_Internal_Rela *relocs,
703 Elf_Internal_Sym *local_syms,
704 asection **local_sections)
705 {
706 Elf_Internal_Shdr *symtab_hdr;
707 struct elf_link_hash_entry **sym_hashes;
708 Elf_Internal_Rela *rel, *relend;
709
710 if (info->relocatable)
711 return TRUE;
712
713 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
714 sym_hashes = elf_sym_hashes (input_bfd);
715
716 rel = relocs;
717 relend = relocs + input_section->reloc_count;
718 for (; rel < relend; rel++)
719 {
720 int r_type;
721 reloc_howto_type *howto;
722 unsigned long r_symndx;
723 Elf_Internal_Sym *sym;
724 asection *sec;
725 struct elf_link_hash_entry *h;
726 bfd_vma relocation;
727 bfd_reloc_status_type r;
728
729 r_symndx = ELF32_R_SYM (rel->r_info);
730 r_type = ELF32_R_TYPE (rel->r_info);
731 howto = crx_elf_howto_table + (r_type);
732
733 h = NULL;
734 sym = NULL;
735 sec = NULL;
736 if (r_symndx < symtab_hdr->sh_info)
737 {
738 sym = local_syms + r_symndx;
739 sec = local_sections[r_symndx];
740 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
741 }
742 else
743 {
744 bfd_boolean unresolved_reloc, warned;
745
746 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
747 r_symndx, symtab_hdr, sym_hashes,
748 h, sec, relocation,
749 unresolved_reloc, warned);
750 }
751
752 r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
753 input_section,
754 contents, rel->r_offset,
755 relocation, rel->r_addend,
756 info, sec, h == NULL);
757
758 if (r != bfd_reloc_ok)
759 {
760 const char *name;
761 const char *msg = (const char *) 0;
762
763 if (h != NULL)
764 name = h->root.root.string;
765 else
766 {
767 name = (bfd_elf_string_from_elf_section
768 (input_bfd, symtab_hdr->sh_link, sym->st_name));
769 if (name == NULL || *name == '\0')
770 name = bfd_section_name (input_bfd, sec);
771 }
772
773 switch (r)
774 {
775 case bfd_reloc_overflow:
776 if (!((*info->callbacks->reloc_overflow)
777 (info, name, howto->name, (bfd_vma) 0,
778 input_bfd, input_section, rel->r_offset)))
779 return FALSE;
780 break;
781
782 case bfd_reloc_undefined:
783 if (!((*info->callbacks->undefined_symbol)
784 (info, name, input_bfd, input_section,
785 rel->r_offset, TRUE)))
786 return FALSE;
787 break;
788
789 case bfd_reloc_outofrange:
790 msg = _("internal error: out of range error");
791 goto common_error;
792
793 case bfd_reloc_notsupported:
794 msg = _("internal error: unsupported relocation error");
795 goto common_error;
796
797 case bfd_reloc_dangerous:
798 msg = _("internal error: dangerous error");
799 goto common_error;
800
801 default:
802 msg = _("internal error: unknown error");
803 /* Fall through. */
804
805 common_error:
806 if (!((*info->callbacks->warning)
807 (info, msg, name, input_bfd, input_section,
808 rel->r_offset)))
809 return FALSE;
810 break;
811 }
812 }
813 }
814
815 return TRUE;
816 }
817
818 /* This function handles relaxing for the CRX.
819
820 There's quite a few relaxing opportunites available on the CRX:
821
822 * bal/bcond:32 -> bal/bcond:16 2 bytes
823 * bcond:16 -> bcond:8 2 bytes
824 * cmpbcond:24 -> cmpbcond:8 2 bytes
825 * arithmetic imm32 -> arithmetic imm16 2 bytes
826
827 Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */
828
829 static bfd_boolean
830 elf32_crx_relax_section (bfd *abfd, asection *sec,
831 struct bfd_link_info *link_info, bfd_boolean *again)
832 {
833 Elf_Internal_Shdr *symtab_hdr;
834 Elf_Internal_Rela *internal_relocs;
835 Elf_Internal_Rela *irel, *irelend;
836 bfd_byte *contents = NULL;
837 Elf_Internal_Sym *isymbuf = NULL;
838
839 /* Assume nothing changes. */
840 *again = FALSE;
841
842 /* We don't have to do anything for a relocatable link, if
843 this section does not have relocs, or if this is not a
844 code section. */
845 if (link_info->relocatable
846 || (sec->flags & SEC_RELOC) == 0
847 || sec->reloc_count == 0
848 || (sec->flags & SEC_CODE) == 0)
849 return TRUE;
850
851 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
852
853 /* Get a copy of the native relocations. */
854 internal_relocs = (_bfd_elf_link_read_relocs
855 (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
856 link_info->keep_memory));
857 if (internal_relocs == NULL)
858 goto error_return;
859
860 /* Walk through them looking for relaxing opportunities. */
861 irelend = internal_relocs + sec->reloc_count;
862 for (irel = internal_relocs; irel < irelend; irel++)
863 {
864 bfd_vma symval;
865
866 /* If this isn't something that can be relaxed, then ignore
867 this reloc. */
868 if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL32
869 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL16
870 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL24
871 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_IMM32)
872 continue;
873
874 /* Get the section contents if we haven't done so already. */
875 if (contents == NULL)
876 {
877 /* Get cached copy if it exists. */
878 if (elf_section_data (sec)->this_hdr.contents != NULL)
879 contents = elf_section_data (sec)->this_hdr.contents;
880 /* Go get them off disk. */
881 else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
882 goto error_return;
883 }
884
885 /* Read this BFD's local symbols if we haven't done so already. */
886 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
887 {
888 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
889 if (isymbuf == NULL)
890 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
891 symtab_hdr->sh_info, 0,
892 NULL, NULL, NULL);
893 if (isymbuf == NULL)
894 goto error_return;
895 }
896
897 /* Get the value of the symbol referred to by the reloc. */
898 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
899 {
900 /* A local symbol. */
901 Elf_Internal_Sym *isym;
902 asection *sym_sec;
903
904 isym = isymbuf + ELF32_R_SYM (irel->r_info);
905 if (isym->st_shndx == SHN_UNDEF)
906 sym_sec = bfd_und_section_ptr;
907 else if (isym->st_shndx == SHN_ABS)
908 sym_sec = bfd_abs_section_ptr;
909 else if (isym->st_shndx == SHN_COMMON)
910 sym_sec = bfd_com_section_ptr;
911 else
912 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
913 symval = (isym->st_value
914 + sym_sec->output_section->vma
915 + sym_sec->output_offset);
916 }
917 else
918 {
919 unsigned long indx;
920 struct elf_link_hash_entry *h;
921
922 /* An external symbol. */
923 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
924 h = elf_sym_hashes (abfd)[indx];
925 BFD_ASSERT (h != NULL);
926
927 if (h->root.type != bfd_link_hash_defined
928 && h->root.type != bfd_link_hash_defweak)
929 /* This appears to be a reference to an undefined
930 symbol. Just ignore it--it will be caught by the
931 regular reloc processing. */
932 continue;
933
934 symval = (h->root.u.def.value
935 + h->root.u.def.section->output_section->vma
936 + h->root.u.def.section->output_offset);
937 }
938
939 /* For simplicity of coding, we are going to modify the section
940 contents, the section relocs, and the BFD symbol table. We
941 must tell the rest of the code not to free up this
942 information. It would be possible to instead create a table
943 of changes which have to be made, as is done in coff-mips.c;
944 that would be more work, but would require less memory when
945 the linker is run. */
946
947 /* Try to turn a 32bit pc-relative branch/call into
948 a 16bit pc-relative branch/call. */
949 if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL32)
950 {
951 bfd_vma value = symval;
952
953 /* Deal with pc-relative gunk. */
954 value -= (sec->output_section->vma + sec->output_offset);
955 value -= irel->r_offset;
956 value += irel->r_addend;
957
958 /* See if the value will fit in 16 bits, note the high value is
959 0xfffe + 2 as the target will be two bytes closer if we are
960 able to relax. */
961 if ((long) value < 0x10000 && (long) value > -0x10002)
962 {
963 unsigned short code;
964
965 /* Get the opcode. */
966 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
967
968 /* Verify it's a 'bal'/'bcond' and fix the opcode. */
969 if ((code & 0xfff0) == 0x3170)
970 bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
971 else if ((code & 0xf0ff) == 0x707f)
972 bfd_put_8 (abfd, 0x7e, contents + irel->r_offset);
973 else
974 continue;
975
976 /* Note that we've changed the relocs, section contents, etc. */
977 elf_section_data (sec)->relocs = internal_relocs;
978 elf_section_data (sec)->this_hdr.contents = contents;
979 symtab_hdr->contents = (unsigned char *) isymbuf;
980
981 /* Fix the relocation's type. */
982 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
983 R_CRX_REL16);
984
985 /* Delete two bytes of data. */
986 if (!elf32_crx_relax_delete_bytes (abfd, sec,
987 irel->r_offset + 2, 2))
988 goto error_return;
989
990 /* That will change things, so, we should relax again.
991 Note that this is not required, and it may be slow. */
992 *again = TRUE;
993 }
994 }
995
996 /* Try to turn a 16bit pc-relative branch into an
997 8bit pc-relative branch. */
998 if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL16)
999 {
1000 bfd_vma value = symval;
1001
1002 /* Deal with pc-relative gunk. */
1003 value -= (sec->output_section->vma + sec->output_offset);
1004 value -= irel->r_offset;
1005 value += irel->r_addend;
1006
1007 /* See if the value will fit in 8 bits, note the high value is
1008 0xfc + 2 as the target will be two bytes closer if we are
1009 able to relax. */
1010 if ((long) value < 0xfe && (long) value > -0x100)
1011 {
1012 unsigned short code;
1013
1014 /* Get the opcode. */
1015 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1016
1017 /* Verify it's a 'bcond' opcode. */
1018 if ((code & 0xf0ff) != 0x707e)
1019 continue;
1020
1021 /* Note that we've changed the relocs, section contents, etc. */
1022 elf_section_data (sec)->relocs = internal_relocs;
1023 elf_section_data (sec)->this_hdr.contents = contents;
1024 symtab_hdr->contents = (unsigned char *) isymbuf;
1025
1026 /* Fix the relocation's type. */
1027 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1028 R_CRX_REL8);
1029
1030 /* Delete two bytes of data. */
1031 if (!elf32_crx_relax_delete_bytes (abfd, sec,
1032 irel->r_offset + 2, 2))
1033 goto error_return;
1034
1035 /* That will change things, so, we should relax again.
1036 Note that this is not required, and it may be slow. */
1037 *again = TRUE;
1038 }
1039 }
1040
1041 /* Try to turn a 24bit pc-relative cmp&branch into
1042 an 8bit pc-relative cmp&branch. */
1043 if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL24)
1044 {
1045 bfd_vma value = symval;
1046
1047 /* Deal with pc-relative gunk. */
1048 value -= (sec->output_section->vma + sec->output_offset);
1049 value -= irel->r_offset;
1050 value += irel->r_addend;
1051
1052 /* See if the value will fit in 8 bits, note the high value is
1053 0x7e + 2 as the target will be two bytes closer if we are
1054 able to relax. */
1055 if ((long) value < 0x100 && (long) value > -0x100)
1056 {
1057 unsigned short code;
1058
1059 /* Get the opcode. */
1060 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1061
1062 /* Verify it's a 'cmp&branch' opcode. */
1063 if ((code & 0xfff0) != 0x3180 && (code & 0xfff0) != 0x3190
1064 && (code & 0xfff0) != 0x31a0 && (code & 0xfff0) != 0x31c0
1065 && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0)
1066 continue;
1067
1068 /* Note that we've changed the relocs, section contents, etc. */
1069 elf_section_data (sec)->relocs = internal_relocs;
1070 elf_section_data (sec)->this_hdr.contents = contents;
1071 symtab_hdr->contents = (unsigned char *) isymbuf;
1072
1073 /* Fix the opcode. */
1074 bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1075
1076 /* Fix the relocation's type. */
1077 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1078 R_CRX_REL8_CMP);
1079
1080 /* Delete two bytes of data. */
1081 if (!elf32_crx_relax_delete_bytes (abfd, sec,
1082 irel->r_offset + 4, 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 32bit immediate address into
1092 a 16bit immediate address. */
1093 if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_IMM32)
1094 {
1095 bfd_vma value = symval;
1096
1097 /* See if the value will fit in 16 bits. */
1098 if ((long) value < 0x7fff && (long) value > -0x8000)
1099 {
1100 unsigned short code;
1101
1102 /* Get the opcode. */
1103 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1104
1105 /* Verify it's a 'arithmetic double'. */
1106 if ((code & 0xf0f0) != 0x20f0)
1107 continue;
1108
1109 /* Note that we've changed the relocs, section contents, etc. */
1110 elf_section_data (sec)->relocs = internal_relocs;
1111 elf_section_data (sec)->this_hdr.contents = contents;
1112 symtab_hdr->contents = (unsigned char *) isymbuf;
1113
1114 /* Fix the opcode. */
1115 bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1116
1117 /* Fix the relocation's type. */
1118 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1119 R_CRX_IMM16);
1120
1121 /* Delete two bytes of data. */
1122 if (!elf32_crx_relax_delete_bytes (abfd, sec,
1123 irel->r_offset + 2, 2))
1124 goto error_return;
1125
1126 /* That will change things, so, we should relax again.
1127 Note that this is not required, and it may be slow. */
1128 *again = TRUE;
1129 }
1130 }
1131 }
1132
1133 if (isymbuf != NULL
1134 && symtab_hdr->contents != (unsigned char *) isymbuf)
1135 {
1136 if (! link_info->keep_memory)
1137 free (isymbuf);
1138 else
1139 {
1140 /* Cache the symbols for elf_link_input_bfd. */
1141 symtab_hdr->contents = (unsigned char *) isymbuf;
1142 }
1143 }
1144
1145 if (contents != NULL
1146 && elf_section_data (sec)->this_hdr.contents != contents)
1147 {
1148 if (! link_info->keep_memory)
1149 free (contents);
1150 else
1151 {
1152 /* Cache the section contents for elf_link_input_bfd. */
1153 elf_section_data (sec)->this_hdr.contents = contents;
1154 }
1155 }
1156
1157 if (internal_relocs != NULL
1158 && elf_section_data (sec)->relocs != internal_relocs)
1159 free (internal_relocs);
1160
1161 return TRUE;
1162
1163 error_return:
1164 if (isymbuf != NULL
1165 && symtab_hdr->contents != (unsigned char *) isymbuf)
1166 free (isymbuf);
1167 if (contents != NULL
1168 && elf_section_data (sec)->this_hdr.contents != contents)
1169 free (contents);
1170 if (internal_relocs != NULL
1171 && elf_section_data (sec)->relocs != internal_relocs)
1172 free (internal_relocs);
1173
1174 return FALSE;
1175 }
1176
1177 static asection *
1178 elf32_crx_gc_mark_hook (asection *sec,
1179 struct bfd_link_info *info ATTRIBUTE_UNUSED,
1180 Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
1181 struct elf_link_hash_entry *h,
1182 Elf_Internal_Sym *sym)
1183 {
1184 if (h == NULL)
1185 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1186
1187 switch (h->root.type)
1188 {
1189 case bfd_link_hash_defined:
1190 case bfd_link_hash_defweak:
1191 return h->root.u.def.section;
1192
1193 case bfd_link_hash_common:
1194 return h->root.u.c.p->section;
1195
1196 default:
1197 return NULL;
1198 }
1199 }
1200
1201 /* Update the got entry reference counts for the section being removed. */
1202
1203 static bfd_boolean
1204 elf32_crx_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
1205 struct bfd_link_info *info ATTRIBUTE_UNUSED,
1206 asection *sec ATTRIBUTE_UNUSED,
1207 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
1208 {
1209 /* We don't support garbage collection of GOT and PLT relocs yet. */
1210 return TRUE;
1211 }
1212
1213 /* Definitions for setting CRX target vector. */
1214 #define TARGET_LITTLE_SYM bfd_elf32_crx_vec
1215 #define TARGET_LITTLE_NAME "elf32-crx"
1216 #define ELF_ARCH bfd_arch_crx
1217 #define ELF_MACHINE_CODE EM_CRX
1218 #define ELF_MAXPAGESIZE 0x1
1219 #define elf_symbol_leading_char '_'
1220
1221 #define bfd_elf32_bfd_reloc_type_lookup elf_crx_reloc_type_lookup
1222 #define elf_info_to_howto elf_crx_info_to_howto
1223 #define elf_info_to_howto_rel 0
1224 #define elf_backend_relocate_section elf32_crx_relocate_section
1225 #define bfd_elf32_bfd_relax_section elf32_crx_relax_section
1226 #define bfd_elf32_bfd_get_relocated_section_contents \
1227 elf32_crx_get_relocated_section_contents
1228 #define elf_backend_gc_mark_hook elf32_crx_gc_mark_hook
1229 #define elf_backend_gc_sweep_hook elf32_crx_gc_sweep_hook
1230 #define elf_backend_can_gc_sections 1
1231 #define elf_backend_rela_normal 1
1232
1233 #include "elf32-target.h"
This page took 0.071234 seconds and 3 git commands to generate.