1 /* Intel i860 specific support for 32-bit ELF.
2 Copyright 1993, 1995, 1999, 2000, 2001, 2002, 2003, 2004
3 Free Software Foundation, Inc.
5 Full i860 support contributed by Jason Eckhardt <jle@cygnus.com>.
7 This file is part of BFD, the Binary File Descriptor library.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
29 /* special_function for R_860_PC26 relocation. */
30 static bfd_reloc_status_type
31 i860_howto_pc26_reloc (bfd *abfd ATTRIBUTE_UNUSED,
34 void *data ATTRIBUTE_UNUSED,
35 asection *input_section,
37 char **error_message ATTRIBUTE_UNUSED)
44 if (output_bfd != NULL
45 && (symbol->flags & BSF_SECTION_SYM) == 0
46 && (! reloc_entry->howto->partial_inplace
47 || reloc_entry->addend == 0))
49 reloc_entry->address += input_section->output_offset;
53 /* Used elf32-mips.c as an example. */
54 if (bfd_is_und_section (symbol->section)
55 && output_bfd == (bfd *) NULL)
56 return bfd_reloc_undefined;
58 if (bfd_is_com_section (symbol->section))
61 relocation = symbol->value;
63 relocation += symbol->section->output_section->vma;
64 relocation += symbol->section->output_offset;
65 relocation += reloc_entry->addend;
67 sz = input_section->rawsize ? input_section->rawsize : input_section->size;
68 if (reloc_entry->address > sz)
69 return bfd_reloc_outofrange;
71 /* Adjust for PC-relative relocation. */
72 relocation -= (input_section->output_section->vma
73 + input_section->output_offset
74 + reloc_entry->address
77 /* Check for target out of range. */
78 if ((bfd_signed_vma)relocation > (0x3ffffff << 2)
79 || (bfd_signed_vma)relocation < (-0x4000000 << 2))
80 return bfd_reloc_outofrange;
82 addr = (bfd_byte *) data + reloc_entry->address;
83 insn = bfd_get_32 (abfd, addr);
85 relocation >>= reloc_entry->howto->rightshift;
86 insn = (insn & ~reloc_entry->howto->dst_mask)
87 | (relocation & reloc_entry->howto->dst_mask);
89 bfd_put_32 (abfd, (bfd_vma) insn, addr);
94 /* special_function for R_860_PC16 relocation. */
95 static bfd_reloc_status_type
96 i860_howto_pc16_reloc (bfd *abfd,
100 asection *input_section,
102 char **error_message ATTRIBUTE_UNUSED)
109 if (output_bfd != NULL
110 && (symbol->flags & BSF_SECTION_SYM) == 0
111 && (! reloc_entry->howto->partial_inplace
112 || reloc_entry->addend == 0))
114 reloc_entry->address += input_section->output_offset;
118 /* Used elf32-mips.c as an example. */
119 if (bfd_is_und_section (symbol->section)
120 && output_bfd == (bfd *) NULL)
121 return bfd_reloc_undefined;
123 if (bfd_is_com_section (symbol->section))
126 relocation = symbol->value;
128 relocation += symbol->section->output_section->vma;
129 relocation += symbol->section->output_offset;
130 relocation += reloc_entry->addend;
132 sz = input_section->rawsize ? input_section->rawsize : input_section->size;
133 if (reloc_entry->address > sz)
134 return bfd_reloc_outofrange;
136 /* Adjust for PC-relative relocation. */
137 relocation -= (input_section->output_section->vma
138 + input_section->output_offset
139 + reloc_entry->address
142 /* Check for target out of range. */
143 if ((bfd_signed_vma)relocation > (0x7fff << 2)
144 || (bfd_signed_vma)relocation < (-0x8000 << 2))
145 return bfd_reloc_outofrange;
147 addr = (bfd_byte *) data + reloc_entry->address;
148 insn = bfd_get_32 (abfd, addr);
150 relocation >>= reloc_entry->howto->rightshift;
151 relocation = (((relocation & 0xf800) << 5) | (relocation & 0x7ff))
152 & reloc_entry->howto->dst_mask;
153 insn = (insn & ~reloc_entry->howto->dst_mask) | relocation;
155 bfd_put_32 (abfd, (bfd_vma) insn, addr);
160 /* special_function for R_860_HIGHADJ relocation. */
161 static bfd_reloc_status_type
162 i860_howto_highadj_reloc (bfd *abfd,
163 arelent *reloc_entry,
166 asection *input_section,
168 char **error_message ATTRIBUTE_UNUSED)
175 if (output_bfd != NULL
176 && (symbol->flags & BSF_SECTION_SYM) == 0
177 && (! reloc_entry->howto->partial_inplace
178 || reloc_entry->addend == 0))
180 reloc_entry->address += input_section->output_offset;
184 /* Used elf32-mips.c as an example. */
185 if (bfd_is_und_section (symbol->section)
186 && output_bfd == (bfd *) NULL)
187 return bfd_reloc_undefined;
189 if (bfd_is_com_section (symbol->section))
192 relocation = symbol->value;
194 relocation += symbol->section->output_section->vma;
195 relocation += symbol->section->output_offset;
196 relocation += reloc_entry->addend;
197 relocation += 0x8000;
199 sz = input_section->rawsize ? input_section->rawsize : input_section->size;
200 if (reloc_entry->address > sz)
201 return bfd_reloc_outofrange;
203 addr = (bfd_byte *) data + reloc_entry->address;
204 insn = bfd_get_32 (abfd, addr);
206 relocation = ((relocation >> 16) & 0xffff);
208 insn = (insn & 0xffff0000) | relocation;
210 bfd_put_32 (abfd, (bfd_vma) insn, addr);
215 /* special_function for R_860_SPLITn relocations. */
216 static bfd_reloc_status_type
217 i860_howto_splitn_reloc (bfd *abfd,
218 arelent *reloc_entry,
221 asection *input_section,
223 char **error_message ATTRIBUTE_UNUSED)
230 if (output_bfd != NULL
231 && (symbol->flags & BSF_SECTION_SYM) == 0
232 && (! reloc_entry->howto->partial_inplace
233 || reloc_entry->addend == 0))
235 reloc_entry->address += input_section->output_offset;
239 /* Used elf32-mips.c as an example. */
240 if (bfd_is_und_section (symbol->section)
241 && output_bfd == (bfd *) NULL)
242 return bfd_reloc_undefined;
244 if (bfd_is_com_section (symbol->section))
247 relocation = symbol->value;
249 relocation += symbol->section->output_section->vma;
250 relocation += symbol->section->output_offset;
251 relocation += reloc_entry->addend;
253 sz = input_section->rawsize ? input_section->rawsize : input_section->size;
254 if (reloc_entry->address > sz)
255 return bfd_reloc_outofrange;
257 addr = (bfd_byte *) data + reloc_entry->address;
258 insn = bfd_get_32 (abfd, addr);
260 relocation = (((relocation & 0xf800) << 5) | (relocation & 0x7ff))
261 & reloc_entry->howto->dst_mask;
262 insn = (insn & ~reloc_entry->howto->dst_mask) | relocation;
264 bfd_put_32 (abfd, (bfd_vma) insn, addr);
269 /* This howto table is preliminary. */
270 static reloc_howto_type elf32_i860_howto_table [] =
272 /* This relocation does nothing. */
273 HOWTO (R_860_NONE, /* type */
275 2, /* size (0 = byte, 1 = short, 2 = long) */
277 FALSE, /* pc_relative */
279 complain_overflow_bitfield, /* complain_on_overflow */
280 bfd_elf_generic_reloc, /* special_function */
281 "R_860_NONE", /* name */
282 FALSE, /* partial_inplace */
285 FALSE), /* pcrel_offset */
287 /* A 32-bit absolute relocation. */
288 HOWTO (R_860_32, /* type */
290 2, /* size (0 = byte, 1 = short, 2 = long) */
292 FALSE, /* pc_relative */
294 complain_overflow_bitfield, /* complain_on_overflow */
295 bfd_elf_generic_reloc, /* special_function */
296 "R_860_32", /* name */
297 FALSE, /* partial_inplace */
298 0xffffffff, /* src_mask */
299 0xffffffff, /* dst_mask */
300 FALSE), /* pcrel_offset */
302 HOWTO (R_860_COPY, /* type */
304 2, /* size (0 = byte, 1 = short, 2 = long) */
306 FALSE, /* pc_relative */
308 complain_overflow_bitfield, /* complain_on_overflow */
309 bfd_elf_generic_reloc, /* special_function */
310 "R_860_COPY", /* name */
311 TRUE, /* partial_inplace */
312 0xffffffff, /* src_mask */
313 0xffffffff, /* dst_mask */
314 FALSE), /* pcrel_offset */
316 HOWTO (R_860_GLOB_DAT, /* type */
318 2, /* size (0 = byte, 1 = short, 2 = long) */
320 FALSE, /* pc_relative */
322 complain_overflow_bitfield, /* complain_on_overflow */
323 bfd_elf_generic_reloc, /* special_function */
324 "R_860_GLOB_DAT", /* name */
325 TRUE, /* partial_inplace */
326 0xffffffff, /* src_mask */
327 0xffffffff, /* dst_mask */
328 FALSE), /* pcrel_offset */
330 HOWTO (R_860_JUMP_SLOT, /* type */
332 2, /* size (0 = byte, 1 = short, 2 = long) */
334 FALSE, /* pc_relative */
336 complain_overflow_bitfield, /* complain_on_overflow */
337 bfd_elf_generic_reloc, /* special_function */
338 "R_860_JUMP_SLOT", /* name */
339 TRUE, /* partial_inplace */
340 0xffffffff, /* src_mask */
341 0xffffffff, /* dst_mask */
342 FALSE), /* pcrel_offset */
344 HOWTO (R_860_RELATIVE, /* type */
346 2, /* size (0 = byte, 1 = short, 2 = long) */
348 FALSE, /* pc_relative */
350 complain_overflow_bitfield, /* complain_on_overflow */
351 bfd_elf_generic_reloc, /* special_function */
352 "R_860_RELATIVE", /* name */
353 TRUE, /* partial_inplace */
354 0xffffffff, /* src_mask */
355 0xffffffff, /* dst_mask */
356 FALSE), /* pcrel_offset */
358 /* A 26-bit PC-relative relocation. */
359 HOWTO (R_860_PC26, /* type */
361 2, /* size (0 = byte, 1 = short, 2 = long) */
363 TRUE, /* pc_relative */
365 complain_overflow_bitfield, /* complain_on_overflow */
366 i860_howto_pc26_reloc, /* special_function */
367 "R_860_PC26", /* name */
368 FALSE, /* partial_inplace */
369 0x3ffffff, /* src_mask */
370 0x3ffffff, /* dst_mask */
371 TRUE), /* pcrel_offset */
373 HOWTO (R_860_PLT26, /* type */
375 2, /* size (0 = byte, 1 = short, 2 = long) */
377 TRUE, /* pc_relative */
379 complain_overflow_bitfield, /* complain_on_overflow */
380 bfd_elf_generic_reloc, /* special_function */
381 "R_860_PLT26", /* name */
382 TRUE, /* partial_inplace */
383 0xffffffff, /* src_mask */
384 0xffffffff, /* dst_mask */
385 TRUE), /* pcrel_offset */
387 /* A 16-bit PC-relative relocation. */
388 HOWTO (R_860_PC16, /* type */
390 2, /* size (0 = byte, 1 = short, 2 = long) */
392 TRUE, /* pc_relative */
394 complain_overflow_bitfield, /* complain_on_overflow */
395 i860_howto_pc16_reloc, /* special_function */
396 "R_860_PC16", /* name */
397 FALSE, /* partial_inplace */
398 0x1f07ff, /* src_mask */
399 0x1f07ff, /* dst_mask */
400 TRUE), /* pcrel_offset */
402 HOWTO (R_860_LOW0, /* type */
404 2, /* size (0 = byte, 1 = short, 2 = long) */
406 FALSE, /* pc_relative */
408 complain_overflow_dont, /* complain_on_overflow */
409 bfd_elf_generic_reloc, /* special_function */
410 "R_860_LOW0", /* name */
411 FALSE, /* partial_inplace */
412 0xffff, /* src_mask */
413 0xffff, /* dst_mask */
414 FALSE), /* pcrel_offset */
416 HOWTO (R_860_SPLIT0, /* type */
418 2, /* size (0 = byte, 1 = short, 2 = long) */
420 FALSE, /* pc_relative */
422 complain_overflow_dont, /* complain_on_overflow */
423 i860_howto_splitn_reloc, /* special_function */
424 "R_860_SPLIT0", /* name */
425 FALSE, /* partial_inplace */
426 0x1f07ff, /* src_mask */
427 0x1f07ff, /* dst_mask */
428 FALSE), /* pcrel_offset */
430 HOWTO (R_860_LOW1, /* type */
432 2, /* size (0 = byte, 1 = short, 2 = long) */
434 FALSE, /* pc_relative */
436 complain_overflow_dont, /* complain_on_overflow */
437 bfd_elf_generic_reloc, /* special_function */
438 "R_860_LOW1", /* name */
439 FALSE, /* partial_inplace */
440 0xfffe, /* src_mask */
441 0xfffe, /* dst_mask */
442 FALSE), /* pcrel_offset */
444 HOWTO (R_860_SPLIT1, /* type */
446 2, /* size (0 = byte, 1 = short, 2 = long) */
448 FALSE, /* pc_relative */
450 complain_overflow_dont, /* complain_on_overflow */
451 i860_howto_splitn_reloc, /* special_function */
452 "R_860_SPLIT1", /* name */
453 FALSE, /* partial_inplace */
454 0x1f07fe, /* src_mask */
455 0x1f07fe, /* dst_mask */
456 FALSE), /* pcrel_offset */
458 HOWTO (R_860_LOW2, /* type */
460 2, /* size (0 = byte, 1 = short, 2 = long) */
462 FALSE, /* pc_relative */
464 complain_overflow_dont, /* complain_on_overflow */
465 bfd_elf_generic_reloc, /* special_function */
466 "R_860_LOW2", /* name */
467 FALSE, /* partial_inplace */
468 0xfffc, /* src_mask */
469 0xfffc, /* dst_mask */
470 FALSE), /* pcrel_offset */
472 HOWTO (R_860_SPLIT2, /* type */
474 2, /* size (0 = byte, 1 = short, 2 = long) */
476 FALSE, /* pc_relative */
478 complain_overflow_dont, /* complain_on_overflow */
479 i860_howto_splitn_reloc, /* special_function */
480 "R_860_SPLIT2", /* name */
481 FALSE, /* partial_inplace */
482 0x1f07fc, /* src_mask */
483 0x1f07fc, /* dst_mask */
484 FALSE), /* pcrel_offset */
486 HOWTO (R_860_LOW3, /* type */
488 2, /* size (0 = byte, 1 = short, 2 = long) */
490 FALSE, /* pc_relative */
492 complain_overflow_dont, /* complain_on_overflow */
493 bfd_elf_generic_reloc, /* special_function */
494 "R_860_LOW3", /* name */
495 FALSE, /* partial_inplace */
496 0xfff8, /* src_mask */
497 0xfff8, /* dst_mask */
498 FALSE), /* pcrel_offset */
500 HOWTO (R_860_LOGOT0, /* type */
502 2, /* size (0 = byte, 1 = short, 2 = long) */
504 FALSE, /* pc_relative */
506 complain_overflow_dont, /* complain_on_overflow */
507 bfd_elf_generic_reloc, /* special_function */
508 "R_860_LOGOT0", /* name */
509 FALSE, /* partial_inplace */
511 0xffff, /* dst_mask */
512 TRUE), /* pcrel_offset */
514 HOWTO (R_860_SPGOT0, /* type */
516 2, /* size (0 = byte, 1 = short, 2 = long) */
518 FALSE, /* pc_relative */
520 complain_overflow_dont, /* complain_on_overflow */
521 bfd_elf_generic_reloc, /* special_function */
522 "R_860_SPGOT0", /* name */
523 FALSE, /* partial_inplace */
525 0xffff, /* dst_mask */
526 TRUE), /* pcrel_offset */
528 HOWTO (R_860_LOGOT1, /* type */
530 2, /* size (0 = byte, 1 = short, 2 = long) */
532 FALSE, /* pc_relative */
534 complain_overflow_dont, /* complain_on_overflow */
535 bfd_elf_generic_reloc, /* special_function */
536 "R_860_LOGOT1", /* name */
537 FALSE, /* partial_inplace */
539 0xffff, /* dst_mask */
540 TRUE), /* pcrel_offset */
542 HOWTO (R_860_SPGOT1, /* type */
544 2, /* size (0 = byte, 1 = short, 2 = long) */
546 FALSE, /* pc_relative */
548 complain_overflow_dont, /* complain_on_overflow */
549 bfd_elf_generic_reloc, /* special_function */
550 "R_860_SPGOT1", /* name */
551 FALSE, /* partial_inplace */
553 0xffff, /* dst_mask */
554 TRUE), /* pcrel_offset */
556 HOWTO (R_860_LOGOTOFF0, /* type */
558 2, /* size (0 = byte, 1 = short, 2 = long) */
560 FALSE, /* pc_relative */
562 complain_overflow_dont, /* complain_on_overflow */
563 bfd_elf_generic_reloc, /* special_function */
564 "R_860_LOGOTOFF0", /* name */
565 TRUE, /* partial_inplace */
566 0xffffffff, /* src_mask */
567 0xffffffff, /* dst_mask */
568 FALSE), /* pcrel_offset */
570 HOWTO (R_860_SPGOTOFF0, /* type */
572 2, /* size (0 = byte, 1 = short, 2 = long) */
574 FALSE, /* pc_relative */
576 complain_overflow_dont, /* complain_on_overflow */
577 bfd_elf_generic_reloc, /* special_function */
578 "R_860_SPGOTOFF0", /* name */
579 TRUE, /* partial_inplace */
580 0xffffffff, /* src_mask */
581 0xffffffff, /* dst_mask */
582 FALSE), /* pcrel_offset */
584 HOWTO (R_860_LOGOTOFF1, /* type */
586 2, /* size (0 = byte, 1 = short, 2 = long) */
588 FALSE, /* pc_relative */
590 complain_overflow_dont, /* complain_on_overflow */
591 bfd_elf_generic_reloc, /* special_function */
592 "R_860_LOGOTOFF1", /* name */
593 TRUE, /* partial_inplace */
594 0xffffffff, /* src_mask */
595 0xffffffff, /* dst_mask */
596 FALSE), /* pcrel_offset */
598 HOWTO (R_860_SPGOTOFF1, /* type */
600 2, /* size (0 = byte, 1 = short, 2 = long) */
602 FALSE, /* pc_relative */
604 complain_overflow_dont, /* complain_on_overflow */
605 bfd_elf_generic_reloc, /* special_function */
606 "R_860_SPGOTOFF1", /* name */
607 TRUE, /* partial_inplace */
608 0xffffffff, /* src_mask */
609 0xffffffff, /* dst_mask */
610 FALSE), /* pcrel_offset */
612 HOWTO (R_860_LOGOTOFF2, /* type */
614 2, /* size (0 = byte, 1 = short, 2 = long) */
616 FALSE, /* pc_relative */
618 complain_overflow_dont, /* complain_on_overflow */
619 bfd_elf_generic_reloc, /* special_function */
620 "R_860_LOGOTOFF2", /* name */
621 TRUE, /* partial_inplace */
622 0xffffffff, /* src_mask */
623 0xffffffff, /* dst_mask */
624 FALSE), /* pcrel_offset */
626 HOWTO (R_860_LOGOTOFF3, /* type */
628 2, /* size (0 = byte, 1 = short, 2 = long) */
630 FALSE, /* pc_relative */
632 complain_overflow_dont, /* complain_on_overflow */
633 bfd_elf_generic_reloc, /* special_function */
634 "R_860_LOGOTOFF3", /* name */
635 TRUE, /* partial_inplace */
636 0xffffffff, /* src_mask */
637 0xffffffff, /* dst_mask */
638 FALSE), /* pcrel_offset */
640 HOWTO (R_860_LOPC, /* type */
642 2, /* size (0 = byte, 1 = short, 2 = long) */
644 TRUE, /* pc_relative */
646 complain_overflow_bitfield, /* complain_on_overflow */
647 bfd_elf_generic_reloc, /* special_function */
648 "R_860_LOPC", /* name */
649 FALSE, /* partial_inplace */
650 0xffff, /* src_mask */
651 0xffff, /* dst_mask */
652 TRUE), /* pcrel_offset */
654 HOWTO (R_860_HIGHADJ, /* type */
656 2, /* size (0 = byte, 1 = short, 2 = long) */
658 FALSE, /* pc_relative */
660 complain_overflow_dont, /* complain_on_overflow */
661 i860_howto_highadj_reloc, /* special_function */
662 "R_860_HIGHADJ", /* name */
663 FALSE, /* partial_inplace */
664 0xffff, /* src_mask */
665 0xffff, /* dst_mask */
666 FALSE), /* pcrel_offset */
668 HOWTO (R_860_HAGOT, /* type */
670 2, /* size (0 = byte, 1 = short, 2 = long) */
672 FALSE, /* pc_relative */
674 complain_overflow_dont, /* complain_on_overflow */
675 bfd_elf_generic_reloc, /* special_function */
676 "R_860_HAGOT", /* name */
677 FALSE, /* partial_inplace */
679 0xffff, /* dst_mask */
680 TRUE), /* pcrel_offset */
682 HOWTO (R_860_HAGOTOFF, /* type */
684 2, /* size (0 = byte, 1 = short, 2 = long) */
686 FALSE, /* pc_relative */
688 complain_overflow_dont, /* complain_on_overflow */
689 bfd_elf_generic_reloc, /* special_function */
690 "R_860_HAGOTOFF", /* name */
691 TRUE, /* partial_inplace */
692 0xffffffff, /* src_mask */
693 0xffffffff, /* dst_mask */
694 FALSE), /* pcrel_offset */
696 HOWTO (R_860_HAPC, /* type */
698 2, /* size (0 = byte, 1 = short, 2 = long) */
700 TRUE, /* pc_relative */
702 complain_overflow_bitfield, /* complain_on_overflow */
703 bfd_elf_generic_reloc, /* special_function */
704 "R_860_HAPC", /* name */
705 FALSE, /* partial_inplace */
706 0xffff, /* src_mask */
707 0xffff, /* dst_mask */
708 TRUE), /* pcrel_offset */
710 HOWTO (R_860_HIGH, /* type */
712 2, /* size (0 = byte, 1 = short, 2 = long) */
714 FALSE, /* pc_relative */
716 complain_overflow_dont, /* complain_on_overflow */
717 bfd_elf_generic_reloc, /* special_function */
718 "R_860_HIGH", /* name */
719 FALSE, /* partial_inplace */
720 0xffff, /* src_mask */
721 0xffff, /* dst_mask */
722 FALSE), /* pcrel_offset */
724 HOWTO (R_860_HIGOT, /* type */
726 2, /* size (0 = byte, 1 = short, 2 = long) */
728 FALSE, /* pc_relative */
730 complain_overflow_dont, /* complain_on_overflow */
731 bfd_elf_generic_reloc, /* special_function */
732 "R_860_HIGOT", /* name */
733 FALSE, /* partial_inplace */
735 0xffff, /* dst_mask */
736 TRUE), /* pcrel_offset */
738 HOWTO (R_860_HIGOTOFF, /* type */
740 2, /* size (0 = byte, 1 = short, 2 = long) */
742 FALSE, /* pc_relative */
744 complain_overflow_dont, /* complain_on_overflow */
745 bfd_elf_generic_reloc, /* special_function */
746 "R_860_HIGOTOFF", /* name */
747 TRUE, /* partial_inplace */
748 0xffffffff, /* src_mask */
749 0xffffffff, /* dst_mask */
750 FALSE), /* pcrel_offset */
753 static unsigned char elf_code_to_howto_index[R_860_max + 1];
755 static reloc_howto_type *
756 lookup_howto (unsigned int rtype)
758 static int initialized = 0;
760 int howto_tbl_size = (int) (sizeof (elf32_i860_howto_table)
761 / sizeof (elf32_i860_howto_table[0]));
766 memset (elf_code_to_howto_index, 0xff,
767 sizeof (elf_code_to_howto_index));
768 for (i = 0; i < howto_tbl_size; i++)
769 elf_code_to_howto_index[elf32_i860_howto_table[i].type] = i;
772 BFD_ASSERT (rtype <= R_860_max);
773 i = elf_code_to_howto_index[rtype];
774 if (i >= howto_tbl_size)
776 return elf32_i860_howto_table + i;
779 /* Given a BFD reloc, return the matching HOWTO structure. */
780 static reloc_howto_type *
781 elf32_i860_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
782 bfd_reloc_code_real_type code)
794 case BFD_RELOC_860_COPY:
797 case BFD_RELOC_860_GLOB_DAT:
798 rtype = R_860_GLOB_DAT;
800 case BFD_RELOC_860_JUMP_SLOT:
801 rtype = R_860_JUMP_SLOT;
803 case BFD_RELOC_860_RELATIVE:
804 rtype = R_860_RELATIVE;
806 case BFD_RELOC_860_PC26:
809 case BFD_RELOC_860_PLT26:
812 case BFD_RELOC_860_PC16:
815 case BFD_RELOC_860_LOW0:
818 case BFD_RELOC_860_SPLIT0:
819 rtype = R_860_SPLIT0;
821 case BFD_RELOC_860_LOW1:
824 case BFD_RELOC_860_SPLIT1:
825 rtype = R_860_SPLIT1;
827 case BFD_RELOC_860_LOW2:
830 case BFD_RELOC_860_SPLIT2:
831 rtype = R_860_SPLIT2;
833 case BFD_RELOC_860_LOW3:
836 case BFD_RELOC_860_LOGOT0:
837 rtype = R_860_LOGOT0;
839 case BFD_RELOC_860_SPGOT0:
840 rtype = R_860_SPGOT0;
842 case BFD_RELOC_860_LOGOT1:
843 rtype = R_860_LOGOT1;
845 case BFD_RELOC_860_SPGOT1:
846 rtype = R_860_SPGOT1;
848 case BFD_RELOC_860_LOGOTOFF0:
849 rtype = R_860_LOGOTOFF0;
851 case BFD_RELOC_860_SPGOTOFF0:
852 rtype = R_860_SPGOTOFF0;
854 case BFD_RELOC_860_LOGOTOFF1:
855 rtype = R_860_LOGOTOFF1;
857 case BFD_RELOC_860_SPGOTOFF1:
858 rtype = R_860_SPGOTOFF1;
860 case BFD_RELOC_860_LOGOTOFF2:
861 rtype = R_860_LOGOTOFF2;
863 case BFD_RELOC_860_LOGOTOFF3:
864 rtype = R_860_LOGOTOFF3;
866 case BFD_RELOC_860_LOPC:
869 case BFD_RELOC_860_HIGHADJ:
870 rtype = R_860_HIGHADJ;
872 case BFD_RELOC_860_HAGOT:
875 case BFD_RELOC_860_HAGOTOFF:
876 rtype = R_860_HAGOTOFF;
878 case BFD_RELOC_860_HAPC:
881 case BFD_RELOC_860_HIGH:
884 case BFD_RELOC_860_HIGOT:
887 case BFD_RELOC_860_HIGOTOFF:
888 rtype = R_860_HIGOTOFF;
894 return lookup_howto (rtype);
897 /* Given a ELF reloc, return the matching HOWTO structure. */
899 elf32_i860_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
901 Elf_Internal_Rela *elf_reloc)
904 = lookup_howto ((unsigned) ELF32_R_TYPE (elf_reloc->r_info));
907 /* Specialized relocation handler for R_860_SPLITn. These relocations
908 involves a 16-bit field that is split into two contiguous parts. */
909 static bfd_reloc_status_type
910 elf32_i860_relocate_splitn (bfd *input_bfd,
911 Elf_Internal_Rela *rello,
916 reloc_howto_type *howto;
917 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
918 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
921 value += rello->r_addend;
923 /* Separate the fields and insert. */
924 value = (((value & 0xf800) << 5) | (value & 0x7ff)) & howto->dst_mask;
925 insn = (insn & ~howto->dst_mask) | value;
927 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
931 /* Specialized relocation handler for R_860_PC16. This relocation
932 involves a 16-bit, PC-relative field that is split into two contiguous
934 static bfd_reloc_status_type
935 elf32_i860_relocate_pc16 (bfd *input_bfd,
936 asection *input_section,
937 Elf_Internal_Rela *rello,
942 reloc_howto_type *howto;
943 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
944 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
946 /* Adjust for PC-relative relocation. */
947 value -= (input_section->output_section->vma
948 + input_section->output_offset);
949 value -= rello->r_offset;
952 value += rello->r_addend;
954 /* Adjust the value by 4, then separate the fields and insert. */
955 value = (value - 4) >> howto->rightshift;
956 value = (((value & 0xf800) << 5) | (value & 0x7ff)) & howto->dst_mask;
957 insn = (insn & ~howto->dst_mask) | value;
959 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
964 /* Specialized relocation handler for R_860_PC26. This relocation
965 involves a 26-bit, PC-relative field which must be adjusted by 4. */
966 static bfd_reloc_status_type
967 elf32_i860_relocate_pc26 (bfd *input_bfd,
968 asection *input_section,
969 Elf_Internal_Rela *rello,
974 reloc_howto_type *howto;
975 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
976 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
978 /* Adjust for PC-relative relocation. */
979 value -= (input_section->output_section->vma
980 + input_section->output_offset);
981 value -= rello->r_offset;
984 value += rello->r_addend;
986 /* Adjust value by 4 and insert the field. */
987 value = ((value - 4) >> howto->rightshift) & howto->dst_mask;
988 insn = (insn & ~howto->dst_mask) | value;
990 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
995 /* Specialized relocation handler for R_860_HIGHADJ. */
996 static bfd_reloc_status_type
997 elf32_i860_relocate_highadj (bfd *input_bfd,
998 Elf_Internal_Rela *rel,
1004 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
1006 value += rel->r_addend;
1008 value = ((value >> 16) & 0xffff);
1010 insn = (insn & 0xffff0000) | value;
1012 bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
1013 return bfd_reloc_ok;
1016 /* Perform a single relocation. By default we use the standard BFD
1017 routines. However, we handle some specially. */
1018 static bfd_reloc_status_type
1019 i860_final_link_relocate (reloc_howto_type *howto,
1021 asection *input_section,
1023 Elf_Internal_Rela *rel,
1026 return _bfd_final_link_relocate (howto, input_bfd, input_section,
1027 contents, rel->r_offset, relocation,
1031 /* Relocate an i860 ELF section.
1033 This is boiler-plate code copied from fr30.
1035 The RELOCATE_SECTION function is called by the new ELF backend linker
1036 to handle the relocations for a section.
1038 The relocs are always passed as Rela structures; if the section
1039 actually uses Rel structures, the r_addend field will always be
1042 This function is responsible for adjusting the section contents as
1043 necessary, and (if using Rela relocs and generating a relocatable
1044 output file) adjusting the reloc addend as necessary.
1046 This function does not have to worry about setting the reloc
1047 address or the reloc symbol index.
1049 LOCAL_SYMS is a pointer to the swapped in local symbols.
1051 LOCAL_SECTIONS is an array giving the section in the input file
1052 corresponding to the st_shndx field of each local symbol.
1054 The global hash table entry for the global symbols can be found
1055 via elf_sym_hashes (input_bfd).
1057 When generating relocatable output, this function must handle
1058 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
1059 going to be the section symbol corresponding to the output
1060 section, which means that the addend must be adjusted
1063 elf32_i860_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
1064 struct bfd_link_info *info,
1066 asection *input_section,
1068 Elf_Internal_Rela *relocs,
1069 Elf_Internal_Sym *local_syms,
1070 asection **local_sections)
1072 Elf_Internal_Shdr *symtab_hdr;
1073 struct elf_link_hash_entry **sym_hashes;
1074 Elf_Internal_Rela *rel;
1075 Elf_Internal_Rela *relend;
1077 if (info->relocatable)
1080 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1081 sym_hashes = elf_sym_hashes (input_bfd);
1082 relend = relocs + input_section->reloc_count;
1084 for (rel = relocs; rel < relend; rel ++)
1086 reloc_howto_type * howto;
1087 unsigned long r_symndx;
1088 Elf_Internal_Sym * sym;
1090 struct elf_link_hash_entry * h;
1092 bfd_reloc_status_type r;
1093 const char * name = NULL;
1096 r_type = ELF32_R_TYPE (rel->r_info);
1099 if ( r_type == R_860_GNU_VTINHERIT
1100 || r_type == R_860_GNU_VTENTRY)
1104 r_symndx = ELF32_R_SYM (rel->r_info);
1106 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
1111 if (r_symndx < symtab_hdr->sh_info)
1113 sym = local_syms + r_symndx;
1114 sec = local_sections [r_symndx];
1115 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1117 name = bfd_elf_string_from_elf_section
1118 (input_bfd, symtab_hdr->sh_link, sym->st_name);
1119 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
1123 bfd_boolean unresolved_reloc, warned;
1125 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1126 r_symndx, symtab_hdr, sym_hashes,
1128 unresolved_reloc, warned);
1134 r = i860_final_link_relocate (howto, input_bfd, input_section,
1135 contents, rel, relocation);
1139 r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
1144 r = elf32_i860_relocate_pc16 (input_bfd, input_section, rel,
1145 contents, relocation);
1149 r = elf32_i860_relocate_pc26 (input_bfd, input_section, rel,
1150 contents, relocation);
1156 r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
1160 /* We do not yet handle GOT/PLT/Dynamic relocations. */
1162 case R_860_GLOB_DAT:
1163 case R_860_JUMP_SLOT:
1164 case R_860_RELATIVE:
1170 case R_860_LOGOTOFF0:
1171 case R_860_SPGOTOFF0:
1172 case R_860_LOGOTOFF1:
1173 case R_860_SPGOTOFF1:
1174 case R_860_LOGOTOFF2:
1175 case R_860_LOGOTOFF3:
1178 case R_860_HAGOTOFF:
1181 case R_860_HIGOTOFF:
1182 r = bfd_reloc_notsupported;
1186 if (r != bfd_reloc_ok)
1188 const char * msg = (const char *) NULL;
1192 case bfd_reloc_overflow:
1193 r = info->callbacks->reloc_overflow
1194 (info, name, howto->name, (bfd_vma) 0,
1195 input_bfd, input_section, rel->r_offset);
1198 case bfd_reloc_undefined:
1199 r = info->callbacks->undefined_symbol
1200 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
1203 case bfd_reloc_outofrange:
1204 msg = _("internal error: out of range error");
1207 case bfd_reloc_notsupported:
1208 msg = _("internal error: unsupported relocation error");
1211 case bfd_reloc_dangerous:
1212 msg = _("internal error: dangerous relocation");
1216 msg = _("internal error: unknown error");
1221 r = info->callbacks->warning
1222 (info, msg, name, input_bfd, input_section, rel->r_offset);
1232 /* Return whether a symbol name implies a local label. SVR4/860 compilers
1233 generate labels of the form ".ep.function_name" to denote the end of a
1234 function prolog. These should be local.
1235 ??? Do any other SVR4 compilers have this convention? If so, this should
1236 be added to the generic routine. */
1238 elf32_i860_is_local_label_name (bfd *abfd, const char *name)
1240 if (name[0] == '.' && name[1] == 'e' && name[2] == 'p' && name[3] == '.')
1243 return _bfd_elf_is_local_label_name (abfd, name);
1246 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1247 #define TARGET_BIG_NAME "elf32-i860"
1248 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1249 #define TARGET_LITTLE_NAME "elf32-i860-little"
1250 #define ELF_ARCH bfd_arch_i860
1251 #define ELF_MACHINE_CODE EM_860
1252 #define ELF_MAXPAGESIZE 4096
1254 #define elf_backend_rela_normal 1
1255 #define elf_info_to_howto_rel NULL
1256 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1257 #define elf_backend_relocate_section elf32_i860_relocate_section
1258 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1259 #define bfd_elf32_bfd_is_local_label_name elf32_i860_is_local_label_name
1261 #include "elf32-target.h"