1 /* Intel i860 specific support for 32-bit ELF.
2 Copyright 1993, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
30 /* special_function for R_860_PC26 relocation. */
31 static bfd_reloc_status_type
32 i860_howto_pc26_reloc (bfd *abfd ATTRIBUTE_UNUSED,
35 void *data ATTRIBUTE_UNUSED,
36 asection *input_section,
38 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 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
68 return bfd_reloc_outofrange;
70 /* Adjust for PC-relative relocation. */
71 relocation -= (input_section->output_section->vma
72 + input_section->output_offset
73 + reloc_entry->address
76 /* Check for target out of range. */
77 if ((bfd_signed_vma)relocation > (0x3ffffff << 2)
78 || (bfd_signed_vma)relocation < (-0x4000000 << 2))
79 return bfd_reloc_outofrange;
81 addr = (bfd_byte *) data + reloc_entry->address;
82 insn = bfd_get_32 (abfd, addr);
84 relocation >>= reloc_entry->howto->rightshift;
85 insn = (insn & ~reloc_entry->howto->dst_mask)
86 | (relocation & reloc_entry->howto->dst_mask);
88 bfd_put_32 (abfd, (bfd_vma) insn, addr);
93 /* special_function for R_860_PC16 relocation. */
94 static bfd_reloc_status_type
95 i860_howto_pc16_reloc (bfd *abfd,
99 asection *input_section,
101 char **error_message ATTRIBUTE_UNUSED)
107 if (output_bfd != NULL
108 && (symbol->flags & BSF_SECTION_SYM) == 0
109 && (! reloc_entry->howto->partial_inplace
110 || reloc_entry->addend == 0))
112 reloc_entry->address += input_section->output_offset;
116 /* Used elf32-mips.c as an example. */
117 if (bfd_is_und_section (symbol->section)
118 && output_bfd == (bfd *) NULL)
119 return bfd_reloc_undefined;
121 if (bfd_is_com_section (symbol->section))
124 relocation = symbol->value;
126 relocation += symbol->section->output_section->vma;
127 relocation += symbol->section->output_offset;
128 relocation += reloc_entry->addend;
130 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
131 return bfd_reloc_outofrange;
133 /* Adjust for PC-relative relocation. */
134 relocation -= (input_section->output_section->vma
135 + input_section->output_offset
136 + reloc_entry->address
139 /* Check for target out of range. */
140 if ((bfd_signed_vma)relocation > (0x7fff << 2)
141 || (bfd_signed_vma)relocation < (-0x8000 << 2))
142 return bfd_reloc_outofrange;
144 addr = (bfd_byte *) data + reloc_entry->address;
145 insn = bfd_get_32 (abfd, addr);
147 relocation >>= reloc_entry->howto->rightshift;
148 relocation = (((relocation & 0xf800) << 5) | (relocation & 0x7ff))
149 & reloc_entry->howto->dst_mask;
150 insn = (insn & ~reloc_entry->howto->dst_mask) | relocation;
152 bfd_put_32 (abfd, (bfd_vma) insn, addr);
157 /* special_function for R_860_HIGHADJ relocation. */
158 static bfd_reloc_status_type
159 i860_howto_highadj_reloc (bfd *abfd,
160 arelent *reloc_entry,
163 asection *input_section,
165 char **error_message ATTRIBUTE_UNUSED)
171 if (output_bfd != NULL
172 && (symbol->flags & BSF_SECTION_SYM) == 0
173 && (! reloc_entry->howto->partial_inplace
174 || reloc_entry->addend == 0))
176 reloc_entry->address += input_section->output_offset;
180 /* Used elf32-mips.c as an example. */
181 if (bfd_is_und_section (symbol->section)
182 && output_bfd == (bfd *) NULL)
183 return bfd_reloc_undefined;
185 if (bfd_is_com_section (symbol->section))
188 relocation = symbol->value;
190 relocation += symbol->section->output_section->vma;
191 relocation += symbol->section->output_offset;
192 relocation += reloc_entry->addend;
193 relocation += 0x8000;
195 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
196 return bfd_reloc_outofrange;
198 addr = (bfd_byte *) data + reloc_entry->address;
199 insn = bfd_get_32 (abfd, addr);
201 relocation = ((relocation >> 16) & 0xffff);
203 insn = (insn & 0xffff0000) | relocation;
205 bfd_put_32 (abfd, (bfd_vma) insn, addr);
210 /* special_function for R_860_SPLITn relocations. */
211 static bfd_reloc_status_type
212 i860_howto_splitn_reloc (bfd *abfd,
213 arelent *reloc_entry,
216 asection *input_section,
218 char **error_message ATTRIBUTE_UNUSED)
224 if (output_bfd != NULL
225 && (symbol->flags & BSF_SECTION_SYM) == 0
226 && (! reloc_entry->howto->partial_inplace
227 || reloc_entry->addend == 0))
229 reloc_entry->address += input_section->output_offset;
233 /* Used elf32-mips.c as an example. */
234 if (bfd_is_und_section (symbol->section)
235 && output_bfd == (bfd *) NULL)
236 return bfd_reloc_undefined;
238 if (bfd_is_com_section (symbol->section))
241 relocation = symbol->value;
243 relocation += symbol->section->output_section->vma;
244 relocation += symbol->section->output_offset;
245 relocation += reloc_entry->addend;
247 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
248 return bfd_reloc_outofrange;
250 addr = (bfd_byte *) data + reloc_entry->address;
251 insn = bfd_get_32 (abfd, addr);
253 relocation = (((relocation & 0xf800) << 5) | (relocation & 0x7ff))
254 & reloc_entry->howto->dst_mask;
255 insn = (insn & ~reloc_entry->howto->dst_mask) | relocation;
257 bfd_put_32 (abfd, (bfd_vma) insn, addr);
262 /* This howto table is preliminary. */
263 static reloc_howto_type elf32_i860_howto_table [] =
265 /* This relocation does nothing. */
266 HOWTO (R_860_NONE, /* type */
268 2, /* size (0 = byte, 1 = short, 2 = long) */
270 FALSE, /* pc_relative */
272 complain_overflow_bitfield, /* complain_on_overflow */
273 bfd_elf_generic_reloc, /* special_function */
274 "R_860_NONE", /* name */
275 FALSE, /* partial_inplace */
278 FALSE), /* pcrel_offset */
280 /* A 32-bit absolute relocation. */
281 HOWTO (R_860_32, /* type */
283 2, /* size (0 = byte, 1 = short, 2 = long) */
285 FALSE, /* pc_relative */
287 complain_overflow_bitfield, /* complain_on_overflow */
288 bfd_elf_generic_reloc, /* special_function */
289 "R_860_32", /* name */
290 FALSE, /* partial_inplace */
291 0xffffffff, /* src_mask */
292 0xffffffff, /* dst_mask */
293 FALSE), /* pcrel_offset */
295 HOWTO (R_860_COPY, /* type */
297 2, /* size (0 = byte, 1 = short, 2 = long) */
299 FALSE, /* pc_relative */
301 complain_overflow_bitfield, /* complain_on_overflow */
302 bfd_elf_generic_reloc, /* special_function */
303 "R_860_COPY", /* name */
304 TRUE, /* partial_inplace */
305 0xffffffff, /* src_mask */
306 0xffffffff, /* dst_mask */
307 FALSE), /* pcrel_offset */
309 HOWTO (R_860_GLOB_DAT, /* type */
311 2, /* size (0 = byte, 1 = short, 2 = long) */
313 FALSE, /* pc_relative */
315 complain_overflow_bitfield, /* complain_on_overflow */
316 bfd_elf_generic_reloc, /* special_function */
317 "R_860_GLOB_DAT", /* name */
318 TRUE, /* partial_inplace */
319 0xffffffff, /* src_mask */
320 0xffffffff, /* dst_mask */
321 FALSE), /* pcrel_offset */
323 HOWTO (R_860_JUMP_SLOT, /* type */
325 2, /* size (0 = byte, 1 = short, 2 = long) */
327 FALSE, /* pc_relative */
329 complain_overflow_bitfield, /* complain_on_overflow */
330 bfd_elf_generic_reloc, /* special_function */
331 "R_860_JUMP_SLOT", /* name */
332 TRUE, /* partial_inplace */
333 0xffffffff, /* src_mask */
334 0xffffffff, /* dst_mask */
335 FALSE), /* pcrel_offset */
337 HOWTO (R_860_RELATIVE, /* type */
339 2, /* size (0 = byte, 1 = short, 2 = long) */
341 FALSE, /* pc_relative */
343 complain_overflow_bitfield, /* complain_on_overflow */
344 bfd_elf_generic_reloc, /* special_function */
345 "R_860_RELATIVE", /* name */
346 TRUE, /* partial_inplace */
347 0xffffffff, /* src_mask */
348 0xffffffff, /* dst_mask */
349 FALSE), /* pcrel_offset */
351 /* A 26-bit PC-relative relocation. */
352 HOWTO (R_860_PC26, /* type */
354 2, /* size (0 = byte, 1 = short, 2 = long) */
356 TRUE, /* pc_relative */
358 complain_overflow_bitfield, /* complain_on_overflow */
359 i860_howto_pc26_reloc, /* special_function */
360 "R_860_PC26", /* name */
361 FALSE, /* partial_inplace */
362 0x3ffffff, /* src_mask */
363 0x3ffffff, /* dst_mask */
364 TRUE), /* pcrel_offset */
366 HOWTO (R_860_PLT26, /* type */
368 2, /* size (0 = byte, 1 = short, 2 = long) */
370 TRUE, /* pc_relative */
372 complain_overflow_bitfield, /* complain_on_overflow */
373 bfd_elf_generic_reloc, /* special_function */
374 "R_860_PLT26", /* name */
375 TRUE, /* partial_inplace */
376 0xffffffff, /* src_mask */
377 0xffffffff, /* dst_mask */
378 TRUE), /* pcrel_offset */
380 /* A 16-bit PC-relative relocation. */
381 HOWTO (R_860_PC16, /* type */
383 2, /* size (0 = byte, 1 = short, 2 = long) */
385 TRUE, /* pc_relative */
387 complain_overflow_bitfield, /* complain_on_overflow */
388 i860_howto_pc16_reloc, /* special_function */
389 "R_860_PC16", /* name */
390 FALSE, /* partial_inplace */
391 0x1f07ff, /* src_mask */
392 0x1f07ff, /* dst_mask */
393 TRUE), /* pcrel_offset */
395 HOWTO (R_860_LOW0, /* type */
397 2, /* size (0 = byte, 1 = short, 2 = long) */
399 FALSE, /* pc_relative */
401 complain_overflow_dont, /* complain_on_overflow */
402 bfd_elf_generic_reloc, /* special_function */
403 "R_860_LOW0", /* name */
404 FALSE, /* partial_inplace */
405 0xffff, /* src_mask */
406 0xffff, /* dst_mask */
407 FALSE), /* pcrel_offset */
409 HOWTO (R_860_SPLIT0, /* type */
411 2, /* size (0 = byte, 1 = short, 2 = long) */
413 FALSE, /* pc_relative */
415 complain_overflow_dont, /* complain_on_overflow */
416 i860_howto_splitn_reloc, /* special_function */
417 "R_860_SPLIT0", /* name */
418 FALSE, /* partial_inplace */
419 0x1f07ff, /* src_mask */
420 0x1f07ff, /* dst_mask */
421 FALSE), /* pcrel_offset */
423 HOWTO (R_860_LOW1, /* type */
425 2, /* size (0 = byte, 1 = short, 2 = long) */
427 FALSE, /* pc_relative */
429 complain_overflow_dont, /* complain_on_overflow */
430 bfd_elf_generic_reloc, /* special_function */
431 "R_860_LOW1", /* name */
432 FALSE, /* partial_inplace */
433 0xfffe, /* src_mask */
434 0xfffe, /* dst_mask */
435 FALSE), /* pcrel_offset */
437 HOWTO (R_860_SPLIT1, /* type */
439 2, /* size (0 = byte, 1 = short, 2 = long) */
441 FALSE, /* pc_relative */
443 complain_overflow_dont, /* complain_on_overflow */
444 i860_howto_splitn_reloc, /* special_function */
445 "R_860_SPLIT1", /* name */
446 FALSE, /* partial_inplace */
447 0x1f07fe, /* src_mask */
448 0x1f07fe, /* dst_mask */
449 FALSE), /* pcrel_offset */
451 HOWTO (R_860_LOW2, /* type */
453 2, /* size (0 = byte, 1 = short, 2 = long) */
455 FALSE, /* pc_relative */
457 complain_overflow_dont, /* complain_on_overflow */
458 bfd_elf_generic_reloc, /* special_function */
459 "R_860_LOW2", /* name */
460 FALSE, /* partial_inplace */
461 0xfffc, /* src_mask */
462 0xfffc, /* dst_mask */
463 FALSE), /* pcrel_offset */
465 HOWTO (R_860_SPLIT2, /* type */
467 2, /* size (0 = byte, 1 = short, 2 = long) */
469 FALSE, /* pc_relative */
471 complain_overflow_dont, /* complain_on_overflow */
472 i860_howto_splitn_reloc, /* special_function */
473 "R_860_SPLIT2", /* name */
474 FALSE, /* partial_inplace */
475 0x1f07fc, /* src_mask */
476 0x1f07fc, /* dst_mask */
477 FALSE), /* pcrel_offset */
479 HOWTO (R_860_LOW3, /* type */
481 2, /* size (0 = byte, 1 = short, 2 = long) */
483 FALSE, /* pc_relative */
485 complain_overflow_dont, /* complain_on_overflow */
486 bfd_elf_generic_reloc, /* special_function */
487 "R_860_LOW3", /* name */
488 FALSE, /* partial_inplace */
489 0xfff8, /* src_mask */
490 0xfff8, /* dst_mask */
491 FALSE), /* pcrel_offset */
493 HOWTO (R_860_LOGOT0, /* type */
495 2, /* size (0 = byte, 1 = short, 2 = long) */
497 FALSE, /* pc_relative */
499 complain_overflow_dont, /* complain_on_overflow */
500 bfd_elf_generic_reloc, /* special_function */
501 "R_860_LOGOT0", /* name */
502 FALSE, /* partial_inplace */
504 0xffff, /* dst_mask */
505 TRUE), /* pcrel_offset */
507 HOWTO (R_860_SPGOT0, /* type */
509 2, /* size (0 = byte, 1 = short, 2 = long) */
511 FALSE, /* pc_relative */
513 complain_overflow_dont, /* complain_on_overflow */
514 bfd_elf_generic_reloc, /* special_function */
515 "R_860_SPGOT0", /* name */
516 FALSE, /* partial_inplace */
518 0xffff, /* dst_mask */
519 TRUE), /* pcrel_offset */
521 HOWTO (R_860_LOGOT1, /* type */
523 2, /* size (0 = byte, 1 = short, 2 = long) */
525 FALSE, /* pc_relative */
527 complain_overflow_dont, /* complain_on_overflow */
528 bfd_elf_generic_reloc, /* special_function */
529 "R_860_LOGOT1", /* name */
530 FALSE, /* partial_inplace */
532 0xffff, /* dst_mask */
533 TRUE), /* pcrel_offset */
535 HOWTO (R_860_SPGOT1, /* type */
537 2, /* size (0 = byte, 1 = short, 2 = long) */
539 FALSE, /* pc_relative */
541 complain_overflow_dont, /* complain_on_overflow */
542 bfd_elf_generic_reloc, /* special_function */
543 "R_860_SPGOT1", /* name */
544 FALSE, /* partial_inplace */
546 0xffff, /* dst_mask */
547 TRUE), /* pcrel_offset */
549 HOWTO (R_860_LOGOTOFF0, /* type */
551 2, /* size (0 = byte, 1 = short, 2 = long) */
553 FALSE, /* pc_relative */
555 complain_overflow_dont, /* complain_on_overflow */
556 bfd_elf_generic_reloc, /* special_function */
557 "R_860_LOGOTOFF0", /* name */
558 TRUE, /* partial_inplace */
559 0xffffffff, /* src_mask */
560 0xffffffff, /* dst_mask */
561 FALSE), /* pcrel_offset */
563 HOWTO (R_860_SPGOTOFF0, /* type */
565 2, /* size (0 = byte, 1 = short, 2 = long) */
567 FALSE, /* pc_relative */
569 complain_overflow_dont, /* complain_on_overflow */
570 bfd_elf_generic_reloc, /* special_function */
571 "R_860_SPGOTOFF0", /* name */
572 TRUE, /* partial_inplace */
573 0xffffffff, /* src_mask */
574 0xffffffff, /* dst_mask */
575 FALSE), /* pcrel_offset */
577 HOWTO (R_860_LOGOTOFF1, /* type */
579 2, /* size (0 = byte, 1 = short, 2 = long) */
581 FALSE, /* pc_relative */
583 complain_overflow_dont, /* complain_on_overflow */
584 bfd_elf_generic_reloc, /* special_function */
585 "R_860_LOGOTOFF1", /* name */
586 TRUE, /* partial_inplace */
587 0xffffffff, /* src_mask */
588 0xffffffff, /* dst_mask */
589 FALSE), /* pcrel_offset */
591 HOWTO (R_860_SPGOTOFF1, /* type */
593 2, /* size (0 = byte, 1 = short, 2 = long) */
595 FALSE, /* pc_relative */
597 complain_overflow_dont, /* complain_on_overflow */
598 bfd_elf_generic_reloc, /* special_function */
599 "R_860_SPGOTOFF1", /* name */
600 TRUE, /* partial_inplace */
601 0xffffffff, /* src_mask */
602 0xffffffff, /* dst_mask */
603 FALSE), /* pcrel_offset */
605 HOWTO (R_860_LOGOTOFF2, /* type */
607 2, /* size (0 = byte, 1 = short, 2 = long) */
609 FALSE, /* pc_relative */
611 complain_overflow_dont, /* complain_on_overflow */
612 bfd_elf_generic_reloc, /* special_function */
613 "R_860_LOGOTOFF2", /* name */
614 TRUE, /* partial_inplace */
615 0xffffffff, /* src_mask */
616 0xffffffff, /* dst_mask */
617 FALSE), /* pcrel_offset */
619 HOWTO (R_860_LOGOTOFF3, /* type */
621 2, /* size (0 = byte, 1 = short, 2 = long) */
623 FALSE, /* pc_relative */
625 complain_overflow_dont, /* complain_on_overflow */
626 bfd_elf_generic_reloc, /* special_function */
627 "R_860_LOGOTOFF3", /* name */
628 TRUE, /* partial_inplace */
629 0xffffffff, /* src_mask */
630 0xffffffff, /* dst_mask */
631 FALSE), /* pcrel_offset */
633 HOWTO (R_860_LOPC, /* type */
635 2, /* size (0 = byte, 1 = short, 2 = long) */
637 TRUE, /* pc_relative */
639 complain_overflow_bitfield, /* complain_on_overflow */
640 bfd_elf_generic_reloc, /* special_function */
641 "R_860_LOPC", /* name */
642 FALSE, /* partial_inplace */
643 0xffff, /* src_mask */
644 0xffff, /* dst_mask */
645 TRUE), /* pcrel_offset */
647 HOWTO (R_860_HIGHADJ, /* type */
649 2, /* size (0 = byte, 1 = short, 2 = long) */
651 FALSE, /* pc_relative */
653 complain_overflow_dont, /* complain_on_overflow */
654 i860_howto_highadj_reloc, /* special_function */
655 "R_860_HIGHADJ", /* name */
656 FALSE, /* partial_inplace */
657 0xffff, /* src_mask */
658 0xffff, /* dst_mask */
659 FALSE), /* pcrel_offset */
661 HOWTO (R_860_HAGOT, /* type */
663 2, /* size (0 = byte, 1 = short, 2 = long) */
665 FALSE, /* pc_relative */
667 complain_overflow_dont, /* complain_on_overflow */
668 bfd_elf_generic_reloc, /* special_function */
669 "R_860_HAGOT", /* name */
670 FALSE, /* partial_inplace */
672 0xffff, /* dst_mask */
673 TRUE), /* pcrel_offset */
675 HOWTO (R_860_HAGOTOFF, /* type */
677 2, /* size (0 = byte, 1 = short, 2 = long) */
679 FALSE, /* pc_relative */
681 complain_overflow_dont, /* complain_on_overflow */
682 bfd_elf_generic_reloc, /* special_function */
683 "R_860_HAGOTOFF", /* name */
684 TRUE, /* partial_inplace */
685 0xffffffff, /* src_mask */
686 0xffffffff, /* dst_mask */
687 FALSE), /* pcrel_offset */
689 HOWTO (R_860_HAPC, /* type */
691 2, /* size (0 = byte, 1 = short, 2 = long) */
693 TRUE, /* pc_relative */
695 complain_overflow_bitfield, /* complain_on_overflow */
696 bfd_elf_generic_reloc, /* special_function */
697 "R_860_HAPC", /* name */
698 FALSE, /* partial_inplace */
699 0xffff, /* src_mask */
700 0xffff, /* dst_mask */
701 TRUE), /* pcrel_offset */
703 HOWTO (R_860_HIGH, /* type */
705 2, /* size (0 = byte, 1 = short, 2 = long) */
707 FALSE, /* pc_relative */
709 complain_overflow_dont, /* complain_on_overflow */
710 bfd_elf_generic_reloc, /* special_function */
711 "R_860_HIGH", /* name */
712 FALSE, /* partial_inplace */
713 0xffff, /* src_mask */
714 0xffff, /* dst_mask */
715 FALSE), /* pcrel_offset */
717 HOWTO (R_860_HIGOT, /* type */
719 2, /* size (0 = byte, 1 = short, 2 = long) */
721 FALSE, /* pc_relative */
723 complain_overflow_dont, /* complain_on_overflow */
724 bfd_elf_generic_reloc, /* special_function */
725 "R_860_HIGOT", /* name */
726 FALSE, /* partial_inplace */
728 0xffff, /* dst_mask */
729 TRUE), /* pcrel_offset */
731 HOWTO (R_860_HIGOTOFF, /* type */
733 2, /* size (0 = byte, 1 = short, 2 = long) */
735 FALSE, /* pc_relative */
737 complain_overflow_dont, /* complain_on_overflow */
738 bfd_elf_generic_reloc, /* special_function */
739 "R_860_HIGOTOFF", /* name */
740 TRUE, /* partial_inplace */
741 0xffffffff, /* src_mask */
742 0xffffffff, /* dst_mask */
743 FALSE), /* pcrel_offset */
746 static unsigned char elf_code_to_howto_index[R_860_max + 1];
748 static reloc_howto_type *
749 lookup_howto (unsigned int rtype)
751 static int initialized = 0;
753 int howto_tbl_size = (int) (sizeof (elf32_i860_howto_table)
754 / sizeof (elf32_i860_howto_table[0]));
759 memset (elf_code_to_howto_index, 0xff,
760 sizeof (elf_code_to_howto_index));
761 for (i = 0; i < howto_tbl_size; i++)
762 elf_code_to_howto_index[elf32_i860_howto_table[i].type] = i;
765 BFD_ASSERT (rtype <= R_860_max);
766 i = elf_code_to_howto_index[rtype];
767 if (i >= howto_tbl_size)
769 return elf32_i860_howto_table + i;
772 /* Given a BFD reloc, return the matching HOWTO structure. */
773 static reloc_howto_type *
774 elf32_i860_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
775 bfd_reloc_code_real_type code)
787 case BFD_RELOC_860_COPY:
790 case BFD_RELOC_860_GLOB_DAT:
791 rtype = R_860_GLOB_DAT;
793 case BFD_RELOC_860_JUMP_SLOT:
794 rtype = R_860_JUMP_SLOT;
796 case BFD_RELOC_860_RELATIVE:
797 rtype = R_860_RELATIVE;
799 case BFD_RELOC_860_PC26:
802 case BFD_RELOC_860_PLT26:
805 case BFD_RELOC_860_PC16:
808 case BFD_RELOC_860_LOW0:
811 case BFD_RELOC_860_SPLIT0:
812 rtype = R_860_SPLIT0;
814 case BFD_RELOC_860_LOW1:
817 case BFD_RELOC_860_SPLIT1:
818 rtype = R_860_SPLIT1;
820 case BFD_RELOC_860_LOW2:
823 case BFD_RELOC_860_SPLIT2:
824 rtype = R_860_SPLIT2;
826 case BFD_RELOC_860_LOW3:
829 case BFD_RELOC_860_LOGOT0:
830 rtype = R_860_LOGOT0;
832 case BFD_RELOC_860_SPGOT0:
833 rtype = R_860_SPGOT0;
835 case BFD_RELOC_860_LOGOT1:
836 rtype = R_860_LOGOT1;
838 case BFD_RELOC_860_SPGOT1:
839 rtype = R_860_SPGOT1;
841 case BFD_RELOC_860_LOGOTOFF0:
842 rtype = R_860_LOGOTOFF0;
844 case BFD_RELOC_860_SPGOTOFF0:
845 rtype = R_860_SPGOTOFF0;
847 case BFD_RELOC_860_LOGOTOFF1:
848 rtype = R_860_LOGOTOFF1;
850 case BFD_RELOC_860_SPGOTOFF1:
851 rtype = R_860_SPGOTOFF1;
853 case BFD_RELOC_860_LOGOTOFF2:
854 rtype = R_860_LOGOTOFF2;
856 case BFD_RELOC_860_LOGOTOFF3:
857 rtype = R_860_LOGOTOFF3;
859 case BFD_RELOC_860_LOPC:
862 case BFD_RELOC_860_HIGHADJ:
863 rtype = R_860_HIGHADJ;
865 case BFD_RELOC_860_HAGOT:
868 case BFD_RELOC_860_HAGOTOFF:
869 rtype = R_860_HAGOTOFF;
871 case BFD_RELOC_860_HAPC:
874 case BFD_RELOC_860_HIGH:
877 case BFD_RELOC_860_HIGOT:
880 case BFD_RELOC_860_HIGOTOFF:
881 rtype = R_860_HIGOTOFF;
887 return lookup_howto (rtype);
890 static reloc_howto_type *
891 elf32_i860_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
897 i < (sizeof (elf32_i860_howto_table)
898 / sizeof (elf32_i860_howto_table[0]));
900 if (elf32_i860_howto_table[i].name != NULL
901 && strcasecmp (elf32_i860_howto_table[i].name, r_name) == 0)
902 return &elf32_i860_howto_table[i];
907 /* Given a ELF reloc, return the matching HOWTO structure. */
909 elf32_i860_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
911 Elf_Internal_Rela *elf_reloc)
914 = lookup_howto ((unsigned) ELF32_R_TYPE (elf_reloc->r_info));
917 /* Specialized relocation handler for R_860_SPLITn. These relocations
918 involves a 16-bit field that is split into two contiguous parts. */
919 static bfd_reloc_status_type
920 elf32_i860_relocate_splitn (bfd *input_bfd,
921 Elf_Internal_Rela *rello,
926 reloc_howto_type *howto;
927 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
928 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
931 value += rello->r_addend;
933 /* Separate the fields and insert. */
934 value = (((value & 0xf800) << 5) | (value & 0x7ff)) & howto->dst_mask;
935 insn = (insn & ~howto->dst_mask) | value;
937 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
941 /* Specialized relocation handler for R_860_PC16. This relocation
942 involves a 16-bit, PC-relative field that is split into two contiguous
944 static bfd_reloc_status_type
945 elf32_i860_relocate_pc16 (bfd *input_bfd,
946 asection *input_section,
947 Elf_Internal_Rela *rello,
952 reloc_howto_type *howto;
953 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
954 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
956 /* Adjust for PC-relative relocation. */
957 value -= (input_section->output_section->vma
958 + input_section->output_offset);
959 value -= rello->r_offset;
962 value += rello->r_addend;
964 /* Adjust the value by 4, then separate the fields and insert. */
965 value = (value - 4) >> howto->rightshift;
966 value = (((value & 0xf800) << 5) | (value & 0x7ff)) & howto->dst_mask;
967 insn = (insn & ~howto->dst_mask) | value;
969 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
974 /* Specialized relocation handler for R_860_PC26. This relocation
975 involves a 26-bit, PC-relative field which must be adjusted by 4. */
976 static bfd_reloc_status_type
977 elf32_i860_relocate_pc26 (bfd *input_bfd,
978 asection *input_section,
979 Elf_Internal_Rela *rello,
984 reloc_howto_type *howto;
985 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
986 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
988 /* Adjust for PC-relative relocation. */
989 value -= (input_section->output_section->vma
990 + input_section->output_offset);
991 value -= rello->r_offset;
994 value += rello->r_addend;
996 /* Adjust value by 4 and insert the field. */
997 value = ((value - 4) >> howto->rightshift) & howto->dst_mask;
998 insn = (insn & ~howto->dst_mask) | value;
1000 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
1001 return bfd_reloc_ok;
1005 /* Specialized relocation handler for R_860_HIGHADJ. */
1006 static bfd_reloc_status_type
1007 elf32_i860_relocate_highadj (bfd *input_bfd,
1008 Elf_Internal_Rela *rel,
1014 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
1016 value += rel->r_addend;
1018 value = ((value >> 16) & 0xffff);
1020 insn = (insn & 0xffff0000) | value;
1022 bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
1023 return bfd_reloc_ok;
1026 /* Perform a single relocation. By default we use the standard BFD
1027 routines. However, we handle some specially. */
1028 static bfd_reloc_status_type
1029 i860_final_link_relocate (reloc_howto_type *howto,
1031 asection *input_section,
1033 Elf_Internal_Rela *rel,
1036 return _bfd_final_link_relocate (howto, input_bfd, input_section,
1037 contents, rel->r_offset, relocation,
1041 /* Relocate an i860 ELF section.
1043 This is boiler-plate code copied from fr30.
1045 The RELOCATE_SECTION function is called by the new ELF backend linker
1046 to handle the relocations for a section.
1048 The relocs are always passed as Rela structures; if the section
1049 actually uses Rel structures, the r_addend field will always be
1052 This function is responsible for adjusting the section contents as
1053 necessary, and (if using Rela relocs and generating a relocatable
1054 output file) adjusting the reloc addend as necessary.
1056 This function does not have to worry about setting the reloc
1057 address or the reloc symbol index.
1059 LOCAL_SYMS is a pointer to the swapped in local symbols.
1061 LOCAL_SECTIONS is an array giving the section in the input file
1062 corresponding to the st_shndx field of each local symbol.
1064 The global hash table entry for the global symbols can be found
1065 via elf_sym_hashes (input_bfd).
1067 When generating relocatable output, this function must handle
1068 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
1069 going to be the section symbol corresponding to the output
1070 section, which means that the addend must be adjusted
1073 elf32_i860_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
1074 struct bfd_link_info *info,
1076 asection *input_section,
1078 Elf_Internal_Rela *relocs,
1079 Elf_Internal_Sym *local_syms,
1080 asection **local_sections)
1082 Elf_Internal_Shdr *symtab_hdr;
1083 struct elf_link_hash_entry **sym_hashes;
1084 Elf_Internal_Rela *rel;
1085 Elf_Internal_Rela *relend;
1087 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1088 sym_hashes = elf_sym_hashes (input_bfd);
1089 relend = relocs + input_section->reloc_count;
1091 for (rel = relocs; rel < relend; rel ++)
1093 reloc_howto_type * howto;
1094 unsigned long r_symndx;
1095 Elf_Internal_Sym * sym;
1097 struct elf_link_hash_entry * h;
1099 bfd_reloc_status_type r;
1100 const char * name = NULL;
1103 r_type = ELF32_R_TYPE (rel->r_info);
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);
1131 if (sec != NULL && elf_discarded_section (sec))
1133 /* For relocs against symbols from removed linkonce sections,
1134 or sections discarded by a linker script, we just want the
1135 section contents zeroed. Avoid any special processing. */
1136 _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
1142 if (info->relocatable)
1148 r = i860_final_link_relocate (howto, input_bfd, input_section,
1149 contents, rel, relocation);
1153 r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
1158 r = elf32_i860_relocate_pc16 (input_bfd, input_section, rel,
1159 contents, relocation);
1163 r = elf32_i860_relocate_pc26 (input_bfd, input_section, rel,
1164 contents, relocation);
1170 r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
1174 /* We do not yet handle GOT/PLT/Dynamic relocations. */
1176 case R_860_GLOB_DAT:
1177 case R_860_JUMP_SLOT:
1178 case R_860_RELATIVE:
1184 case R_860_LOGOTOFF0:
1185 case R_860_SPGOTOFF0:
1186 case R_860_LOGOTOFF1:
1187 case R_860_SPGOTOFF1:
1188 case R_860_LOGOTOFF2:
1189 case R_860_LOGOTOFF3:
1192 case R_860_HAGOTOFF:
1195 case R_860_HIGOTOFF:
1196 r = bfd_reloc_notsupported;
1200 if (r != bfd_reloc_ok)
1202 const char * msg = (const char *) NULL;
1206 case bfd_reloc_overflow:
1207 r = info->callbacks->reloc_overflow
1208 (info, (h ? &h->root : NULL), name, howto->name,
1209 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
1212 case bfd_reloc_undefined:
1213 r = info->callbacks->undefined_symbol
1214 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
1217 case bfd_reloc_outofrange:
1218 msg = _("internal error: out of range error");
1221 case bfd_reloc_notsupported:
1222 msg = _("internal error: unsupported relocation error");
1225 case bfd_reloc_dangerous:
1226 msg = _("internal error: dangerous relocation");
1230 msg = _("internal error: unknown error");
1235 r = info->callbacks->warning
1236 (info, msg, name, input_bfd, input_section, rel->r_offset);
1246 /* Return whether a symbol name implies a local label. SVR4/860 compilers
1247 generate labels of the form ".ep.function_name" to denote the end of a
1248 function prolog. These should be local.
1249 ??? Do any other SVR4 compilers have this convention? If so, this should
1250 be added to the generic routine. */
1252 elf32_i860_is_local_label_name (bfd *abfd, const char *name)
1254 if (name[0] == '.' && name[1] == 'e' && name[2] == 'p' && name[3] == '.')
1257 return _bfd_elf_is_local_label_name (abfd, name);
1260 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1261 #define TARGET_BIG_NAME "elf32-i860"
1262 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1263 #define TARGET_LITTLE_NAME "elf32-i860-little"
1264 #define ELF_ARCH bfd_arch_i860
1265 #define ELF_MACHINE_CODE EM_860
1266 #define ELF_MAXPAGESIZE 4096
1268 #define elf_backend_rela_normal 1
1269 #define elf_info_to_howto_rel NULL
1270 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1271 #define elf_backend_relocate_section elf32_i860_relocate_section
1272 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1273 #define bfd_elf32_bfd_reloc_name_lookup elf32_i860_reloc_name_lookup
1274 #define bfd_elf32_bfd_is_local_label_name elf32_i860_is_local_label_name
1276 #include "elf32-target.h"