1 /* Intel i860 specific support for 32-bit ELF.
2 Copyright 1993, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008,
4 Free Software Foundation, Inc.
6 Full i860 support contributed by Jason Eckhardt <jle@cygnus.com>.
8 This file is part of BFD, the Binary File Descriptor library.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
31 /* special_function for R_860_PC26 relocation. */
32 static bfd_reloc_status_type
33 i860_howto_pc26_reloc (bfd
*abfd ATTRIBUTE_UNUSED
,
36 void *data ATTRIBUTE_UNUSED
,
37 asection
*input_section
,
39 char **error_message ATTRIBUTE_UNUSED
)
45 if (output_bfd
!= NULL
46 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
47 && (! reloc_entry
->howto
->partial_inplace
48 || reloc_entry
->addend
== 0))
50 reloc_entry
->address
+= input_section
->output_offset
;
54 /* Used elf32-mips.c as an example. */
55 if (bfd_is_und_section (symbol
->section
)
56 && output_bfd
== (bfd
*) NULL
)
57 return bfd_reloc_undefined
;
59 if (bfd_is_com_section (symbol
->section
))
62 relocation
= symbol
->value
;
64 relocation
+= symbol
->section
->output_section
->vma
;
65 relocation
+= symbol
->section
->output_offset
;
66 relocation
+= reloc_entry
->addend
;
68 if (reloc_entry
->address
> bfd_get_section_limit (abfd
, input_section
))
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
)
108 if (output_bfd
!= NULL
109 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
110 && (! reloc_entry
->howto
->partial_inplace
111 || reloc_entry
->addend
== 0))
113 reloc_entry
->address
+= input_section
->output_offset
;
117 /* Used elf32-mips.c as an example. */
118 if (bfd_is_und_section (symbol
->section
)
119 && output_bfd
== (bfd
*) NULL
)
120 return bfd_reloc_undefined
;
122 if (bfd_is_com_section (symbol
->section
))
125 relocation
= symbol
->value
;
127 relocation
+= symbol
->section
->output_section
->vma
;
128 relocation
+= symbol
->section
->output_offset
;
129 relocation
+= reloc_entry
->addend
;
131 if (reloc_entry
->address
> bfd_get_section_limit (abfd
, input_section
))
132 return bfd_reloc_outofrange
;
134 /* Adjust for PC-relative relocation. */
135 relocation
-= (input_section
->output_section
->vma
136 + input_section
->output_offset
137 + reloc_entry
->address
140 /* Check for target out of range. */
141 if ((bfd_signed_vma
)relocation
> (0x7fff << 2)
142 || (bfd_signed_vma
)relocation
< (-0x8000 << 2))
143 return bfd_reloc_outofrange
;
145 addr
= (bfd_byte
*) data
+ reloc_entry
->address
;
146 insn
= bfd_get_32 (abfd
, addr
);
148 relocation
>>= reloc_entry
->howto
->rightshift
;
149 relocation
= (((relocation
& 0xf800) << 5) | (relocation
& 0x7ff))
150 & reloc_entry
->howto
->dst_mask
;
151 insn
= (insn
& ~reloc_entry
->howto
->dst_mask
) | relocation
;
153 bfd_put_32 (abfd
, (bfd_vma
) insn
, addr
);
158 /* special_function for R_860_HIGHADJ relocation. */
159 static bfd_reloc_status_type
160 i860_howto_highadj_reloc (bfd
*abfd
,
161 arelent
*reloc_entry
,
164 asection
*input_section
,
166 char **error_message ATTRIBUTE_UNUSED
)
172 if (output_bfd
!= NULL
173 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
174 && (! reloc_entry
->howto
->partial_inplace
175 || reloc_entry
->addend
== 0))
177 reloc_entry
->address
+= input_section
->output_offset
;
181 /* Used elf32-mips.c as an example. */
182 if (bfd_is_und_section (symbol
->section
)
183 && output_bfd
== (bfd
*) NULL
)
184 return bfd_reloc_undefined
;
186 if (bfd_is_com_section (symbol
->section
))
189 relocation
= symbol
->value
;
191 relocation
+= symbol
->section
->output_section
->vma
;
192 relocation
+= symbol
->section
->output_offset
;
193 relocation
+= reloc_entry
->addend
;
194 relocation
+= 0x8000;
196 if (reloc_entry
->address
> bfd_get_section_limit (abfd
, input_section
))
197 return bfd_reloc_outofrange
;
199 addr
= (bfd_byte
*) data
+ reloc_entry
->address
;
200 insn
= bfd_get_32 (abfd
, addr
);
202 relocation
= ((relocation
>> 16) & 0xffff);
204 insn
= (insn
& 0xffff0000) | relocation
;
206 bfd_put_32 (abfd
, (bfd_vma
) insn
, addr
);
211 /* special_function for R_860_SPLITn relocations. */
212 static bfd_reloc_status_type
213 i860_howto_splitn_reloc (bfd
*abfd
,
214 arelent
*reloc_entry
,
217 asection
*input_section
,
219 char **error_message ATTRIBUTE_UNUSED
)
225 if (output_bfd
!= NULL
226 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
227 && (! reloc_entry
->howto
->partial_inplace
228 || reloc_entry
->addend
== 0))
230 reloc_entry
->address
+= input_section
->output_offset
;
234 /* Used elf32-mips.c as an example. */
235 if (bfd_is_und_section (symbol
->section
)
236 && output_bfd
== (bfd
*) NULL
)
237 return bfd_reloc_undefined
;
239 if (bfd_is_com_section (symbol
->section
))
242 relocation
= symbol
->value
;
244 relocation
+= symbol
->section
->output_section
->vma
;
245 relocation
+= symbol
->section
->output_offset
;
246 relocation
+= reloc_entry
->addend
;
248 if (reloc_entry
->address
> bfd_get_section_limit (abfd
, input_section
))
249 return bfd_reloc_outofrange
;
251 addr
= (bfd_byte
*) data
+ reloc_entry
->address
;
252 insn
= bfd_get_32 (abfd
, addr
);
254 relocation
= (((relocation
& 0xf800) << 5) | (relocation
& 0x7ff))
255 & reloc_entry
->howto
->dst_mask
;
256 insn
= (insn
& ~reloc_entry
->howto
->dst_mask
) | relocation
;
258 bfd_put_32 (abfd
, (bfd_vma
) insn
, addr
);
263 /* This howto table is preliminary. */
264 static reloc_howto_type elf32_i860_howto_table
[] =
266 /* This relocation does nothing. */
267 HOWTO (R_860_NONE
, /* type */
269 2, /* size (0 = byte, 1 = short, 2 = long) */
271 FALSE
, /* pc_relative */
273 complain_overflow_bitfield
, /* complain_on_overflow */
274 bfd_elf_generic_reloc
, /* special_function */
275 "R_860_NONE", /* name */
276 FALSE
, /* partial_inplace */
279 FALSE
), /* pcrel_offset */
281 /* A 32-bit absolute relocation. */
282 HOWTO (R_860_32
, /* type */
284 2, /* size (0 = byte, 1 = short, 2 = long) */
286 FALSE
, /* pc_relative */
288 complain_overflow_bitfield
, /* complain_on_overflow */
289 bfd_elf_generic_reloc
, /* special_function */
290 "R_860_32", /* name */
291 FALSE
, /* partial_inplace */
292 0xffffffff, /* src_mask */
293 0xffffffff, /* dst_mask */
294 FALSE
), /* pcrel_offset */
296 HOWTO (R_860_COPY
, /* type */
298 2, /* size (0 = byte, 1 = short, 2 = long) */
300 FALSE
, /* pc_relative */
302 complain_overflow_bitfield
, /* complain_on_overflow */
303 bfd_elf_generic_reloc
, /* special_function */
304 "R_860_COPY", /* name */
305 TRUE
, /* partial_inplace */
306 0xffffffff, /* src_mask */
307 0xffffffff, /* dst_mask */
308 FALSE
), /* pcrel_offset */
310 HOWTO (R_860_GLOB_DAT
, /* type */
312 2, /* size (0 = byte, 1 = short, 2 = long) */
314 FALSE
, /* pc_relative */
316 complain_overflow_bitfield
, /* complain_on_overflow */
317 bfd_elf_generic_reloc
, /* special_function */
318 "R_860_GLOB_DAT", /* name */
319 TRUE
, /* partial_inplace */
320 0xffffffff, /* src_mask */
321 0xffffffff, /* dst_mask */
322 FALSE
), /* pcrel_offset */
324 HOWTO (R_860_JUMP_SLOT
, /* type */
326 2, /* size (0 = byte, 1 = short, 2 = long) */
328 FALSE
, /* pc_relative */
330 complain_overflow_bitfield
, /* complain_on_overflow */
331 bfd_elf_generic_reloc
, /* special_function */
332 "R_860_JUMP_SLOT", /* name */
333 TRUE
, /* partial_inplace */
334 0xffffffff, /* src_mask */
335 0xffffffff, /* dst_mask */
336 FALSE
), /* pcrel_offset */
338 HOWTO (R_860_RELATIVE
, /* type */
340 2, /* size (0 = byte, 1 = short, 2 = long) */
342 FALSE
, /* pc_relative */
344 complain_overflow_bitfield
, /* complain_on_overflow */
345 bfd_elf_generic_reloc
, /* special_function */
346 "R_860_RELATIVE", /* name */
347 TRUE
, /* partial_inplace */
348 0xffffffff, /* src_mask */
349 0xffffffff, /* dst_mask */
350 FALSE
), /* pcrel_offset */
352 /* A 26-bit PC-relative relocation. */
353 HOWTO (R_860_PC26
, /* type */
355 2, /* size (0 = byte, 1 = short, 2 = long) */
357 TRUE
, /* pc_relative */
359 complain_overflow_bitfield
, /* complain_on_overflow */
360 i860_howto_pc26_reloc
, /* special_function */
361 "R_860_PC26", /* name */
362 FALSE
, /* partial_inplace */
363 0x3ffffff, /* src_mask */
364 0x3ffffff, /* dst_mask */
365 TRUE
), /* pcrel_offset */
367 HOWTO (R_860_PLT26
, /* type */
369 2, /* size (0 = byte, 1 = short, 2 = long) */
371 TRUE
, /* pc_relative */
373 complain_overflow_bitfield
, /* complain_on_overflow */
374 bfd_elf_generic_reloc
, /* special_function */
375 "R_860_PLT26", /* name */
376 TRUE
, /* partial_inplace */
377 0xffffffff, /* src_mask */
378 0xffffffff, /* dst_mask */
379 TRUE
), /* pcrel_offset */
381 /* A 16-bit PC-relative relocation. */
382 HOWTO (R_860_PC16
, /* type */
384 2, /* size (0 = byte, 1 = short, 2 = long) */
386 TRUE
, /* pc_relative */
388 complain_overflow_bitfield
, /* complain_on_overflow */
389 i860_howto_pc16_reloc
, /* special_function */
390 "R_860_PC16", /* name */
391 FALSE
, /* partial_inplace */
392 0x1f07ff, /* src_mask */
393 0x1f07ff, /* dst_mask */
394 TRUE
), /* pcrel_offset */
396 HOWTO (R_860_LOW0
, /* type */
398 2, /* size (0 = byte, 1 = short, 2 = long) */
400 FALSE
, /* pc_relative */
402 complain_overflow_dont
, /* complain_on_overflow */
403 bfd_elf_generic_reloc
, /* special_function */
404 "R_860_LOW0", /* name */
405 FALSE
, /* partial_inplace */
406 0xffff, /* src_mask */
407 0xffff, /* dst_mask */
408 FALSE
), /* pcrel_offset */
410 HOWTO (R_860_SPLIT0
, /* type */
412 2, /* size (0 = byte, 1 = short, 2 = long) */
414 FALSE
, /* pc_relative */
416 complain_overflow_dont
, /* complain_on_overflow */
417 i860_howto_splitn_reloc
, /* special_function */
418 "R_860_SPLIT0", /* name */
419 FALSE
, /* partial_inplace */
420 0x1f07ff, /* src_mask */
421 0x1f07ff, /* dst_mask */
422 FALSE
), /* pcrel_offset */
424 HOWTO (R_860_LOW1
, /* type */
426 2, /* size (0 = byte, 1 = short, 2 = long) */
428 FALSE
, /* pc_relative */
430 complain_overflow_dont
, /* complain_on_overflow */
431 bfd_elf_generic_reloc
, /* special_function */
432 "R_860_LOW1", /* name */
433 FALSE
, /* partial_inplace */
434 0xfffe, /* src_mask */
435 0xfffe, /* dst_mask */
436 FALSE
), /* pcrel_offset */
438 HOWTO (R_860_SPLIT1
, /* type */
440 2, /* size (0 = byte, 1 = short, 2 = long) */
442 FALSE
, /* pc_relative */
444 complain_overflow_dont
, /* complain_on_overflow */
445 i860_howto_splitn_reloc
, /* special_function */
446 "R_860_SPLIT1", /* name */
447 FALSE
, /* partial_inplace */
448 0x1f07fe, /* src_mask */
449 0x1f07fe, /* dst_mask */
450 FALSE
), /* pcrel_offset */
452 HOWTO (R_860_LOW2
, /* type */
454 2, /* size (0 = byte, 1 = short, 2 = long) */
456 FALSE
, /* pc_relative */
458 complain_overflow_dont
, /* complain_on_overflow */
459 bfd_elf_generic_reloc
, /* special_function */
460 "R_860_LOW2", /* name */
461 FALSE
, /* partial_inplace */
462 0xfffc, /* src_mask */
463 0xfffc, /* dst_mask */
464 FALSE
), /* pcrel_offset */
466 HOWTO (R_860_SPLIT2
, /* type */
468 2, /* size (0 = byte, 1 = short, 2 = long) */
470 FALSE
, /* pc_relative */
472 complain_overflow_dont
, /* complain_on_overflow */
473 i860_howto_splitn_reloc
, /* special_function */
474 "R_860_SPLIT2", /* name */
475 FALSE
, /* partial_inplace */
476 0x1f07fc, /* src_mask */
477 0x1f07fc, /* dst_mask */
478 FALSE
), /* pcrel_offset */
480 HOWTO (R_860_LOW3
, /* type */
482 2, /* size (0 = byte, 1 = short, 2 = long) */
484 FALSE
, /* pc_relative */
486 complain_overflow_dont
, /* complain_on_overflow */
487 bfd_elf_generic_reloc
, /* special_function */
488 "R_860_LOW3", /* name */
489 FALSE
, /* partial_inplace */
490 0xfff8, /* src_mask */
491 0xfff8, /* dst_mask */
492 FALSE
), /* pcrel_offset */
494 HOWTO (R_860_LOGOT0
, /* type */
496 2, /* size (0 = byte, 1 = short, 2 = long) */
498 FALSE
, /* pc_relative */
500 complain_overflow_dont
, /* complain_on_overflow */
501 bfd_elf_generic_reloc
, /* special_function */
502 "R_860_LOGOT0", /* name */
503 FALSE
, /* partial_inplace */
505 0xffff, /* dst_mask */
506 TRUE
), /* pcrel_offset */
508 HOWTO (R_860_SPGOT0
, /* type */
510 2, /* size (0 = byte, 1 = short, 2 = long) */
512 FALSE
, /* pc_relative */
514 complain_overflow_dont
, /* complain_on_overflow */
515 bfd_elf_generic_reloc
, /* special_function */
516 "R_860_SPGOT0", /* name */
517 FALSE
, /* partial_inplace */
519 0xffff, /* dst_mask */
520 TRUE
), /* pcrel_offset */
522 HOWTO (R_860_LOGOT1
, /* type */
524 2, /* size (0 = byte, 1 = short, 2 = long) */
526 FALSE
, /* pc_relative */
528 complain_overflow_dont
, /* complain_on_overflow */
529 bfd_elf_generic_reloc
, /* special_function */
530 "R_860_LOGOT1", /* name */
531 FALSE
, /* partial_inplace */
533 0xffff, /* dst_mask */
534 TRUE
), /* pcrel_offset */
536 HOWTO (R_860_SPGOT1
, /* type */
538 2, /* size (0 = byte, 1 = short, 2 = long) */
540 FALSE
, /* pc_relative */
542 complain_overflow_dont
, /* complain_on_overflow */
543 bfd_elf_generic_reloc
, /* special_function */
544 "R_860_SPGOT1", /* name */
545 FALSE
, /* partial_inplace */
547 0xffff, /* dst_mask */
548 TRUE
), /* pcrel_offset */
550 HOWTO (R_860_LOGOTOFF0
, /* type */
552 2, /* size (0 = byte, 1 = short, 2 = long) */
554 FALSE
, /* pc_relative */
556 complain_overflow_dont
, /* complain_on_overflow */
557 bfd_elf_generic_reloc
, /* special_function */
558 "R_860_LOGOTOFF0", /* name */
559 TRUE
, /* partial_inplace */
560 0xffffffff, /* src_mask */
561 0xffffffff, /* dst_mask */
562 FALSE
), /* pcrel_offset */
564 HOWTO (R_860_SPGOTOFF0
, /* type */
566 2, /* size (0 = byte, 1 = short, 2 = long) */
568 FALSE
, /* pc_relative */
570 complain_overflow_dont
, /* complain_on_overflow */
571 bfd_elf_generic_reloc
, /* special_function */
572 "R_860_SPGOTOFF0", /* name */
573 TRUE
, /* partial_inplace */
574 0xffffffff, /* src_mask */
575 0xffffffff, /* dst_mask */
576 FALSE
), /* pcrel_offset */
578 HOWTO (R_860_LOGOTOFF1
, /* type */
580 2, /* size (0 = byte, 1 = short, 2 = long) */
582 FALSE
, /* pc_relative */
584 complain_overflow_dont
, /* complain_on_overflow */
585 bfd_elf_generic_reloc
, /* special_function */
586 "R_860_LOGOTOFF1", /* name */
587 TRUE
, /* partial_inplace */
588 0xffffffff, /* src_mask */
589 0xffffffff, /* dst_mask */
590 FALSE
), /* pcrel_offset */
592 HOWTO (R_860_SPGOTOFF1
, /* type */
594 2, /* size (0 = byte, 1 = short, 2 = long) */
596 FALSE
, /* pc_relative */
598 complain_overflow_dont
, /* complain_on_overflow */
599 bfd_elf_generic_reloc
, /* special_function */
600 "R_860_SPGOTOFF1", /* name */
601 TRUE
, /* partial_inplace */
602 0xffffffff, /* src_mask */
603 0xffffffff, /* dst_mask */
604 FALSE
), /* pcrel_offset */
606 HOWTO (R_860_LOGOTOFF2
, /* type */
608 2, /* size (0 = byte, 1 = short, 2 = long) */
610 FALSE
, /* pc_relative */
612 complain_overflow_dont
, /* complain_on_overflow */
613 bfd_elf_generic_reloc
, /* special_function */
614 "R_860_LOGOTOFF2", /* name */
615 TRUE
, /* partial_inplace */
616 0xffffffff, /* src_mask */
617 0xffffffff, /* dst_mask */
618 FALSE
), /* pcrel_offset */
620 HOWTO (R_860_LOGOTOFF3
, /* type */
622 2, /* size (0 = byte, 1 = short, 2 = long) */
624 FALSE
, /* pc_relative */
626 complain_overflow_dont
, /* complain_on_overflow */
627 bfd_elf_generic_reloc
, /* special_function */
628 "R_860_LOGOTOFF3", /* name */
629 TRUE
, /* partial_inplace */
630 0xffffffff, /* src_mask */
631 0xffffffff, /* dst_mask */
632 FALSE
), /* pcrel_offset */
634 HOWTO (R_860_LOPC
, /* type */
636 2, /* size (0 = byte, 1 = short, 2 = long) */
638 TRUE
, /* pc_relative */
640 complain_overflow_bitfield
, /* complain_on_overflow */
641 bfd_elf_generic_reloc
, /* special_function */
642 "R_860_LOPC", /* name */
643 FALSE
, /* partial_inplace */
644 0xffff, /* src_mask */
645 0xffff, /* dst_mask */
646 TRUE
), /* pcrel_offset */
648 HOWTO (R_860_HIGHADJ
, /* type */
650 2, /* size (0 = byte, 1 = short, 2 = long) */
652 FALSE
, /* pc_relative */
654 complain_overflow_dont
, /* complain_on_overflow */
655 i860_howto_highadj_reloc
, /* special_function */
656 "R_860_HIGHADJ", /* name */
657 FALSE
, /* partial_inplace */
658 0xffff, /* src_mask */
659 0xffff, /* dst_mask */
660 FALSE
), /* pcrel_offset */
662 HOWTO (R_860_HAGOT
, /* type */
664 2, /* size (0 = byte, 1 = short, 2 = long) */
666 FALSE
, /* pc_relative */
668 complain_overflow_dont
, /* complain_on_overflow */
669 bfd_elf_generic_reloc
, /* special_function */
670 "R_860_HAGOT", /* name */
671 FALSE
, /* partial_inplace */
673 0xffff, /* dst_mask */
674 TRUE
), /* pcrel_offset */
676 HOWTO (R_860_HAGOTOFF
, /* type */
678 2, /* size (0 = byte, 1 = short, 2 = long) */
680 FALSE
, /* pc_relative */
682 complain_overflow_dont
, /* complain_on_overflow */
683 bfd_elf_generic_reloc
, /* special_function */
684 "R_860_HAGOTOFF", /* name */
685 TRUE
, /* partial_inplace */
686 0xffffffff, /* src_mask */
687 0xffffffff, /* dst_mask */
688 FALSE
), /* pcrel_offset */
690 HOWTO (R_860_HAPC
, /* type */
692 2, /* size (0 = byte, 1 = short, 2 = long) */
694 TRUE
, /* pc_relative */
696 complain_overflow_bitfield
, /* complain_on_overflow */
697 bfd_elf_generic_reloc
, /* special_function */
698 "R_860_HAPC", /* name */
699 FALSE
, /* partial_inplace */
700 0xffff, /* src_mask */
701 0xffff, /* dst_mask */
702 TRUE
), /* pcrel_offset */
704 HOWTO (R_860_HIGH
, /* type */
706 2, /* size (0 = byte, 1 = short, 2 = long) */
708 FALSE
, /* pc_relative */
710 complain_overflow_dont
, /* complain_on_overflow */
711 bfd_elf_generic_reloc
, /* special_function */
712 "R_860_HIGH", /* name */
713 FALSE
, /* partial_inplace */
714 0xffff, /* src_mask */
715 0xffff, /* dst_mask */
716 FALSE
), /* pcrel_offset */
718 HOWTO (R_860_HIGOT
, /* type */
720 2, /* size (0 = byte, 1 = short, 2 = long) */
722 FALSE
, /* pc_relative */
724 complain_overflow_dont
, /* complain_on_overflow */
725 bfd_elf_generic_reloc
, /* special_function */
726 "R_860_HIGOT", /* name */
727 FALSE
, /* partial_inplace */
729 0xffff, /* dst_mask */
730 TRUE
), /* pcrel_offset */
732 HOWTO (R_860_HIGOTOFF
, /* type */
734 2, /* size (0 = byte, 1 = short, 2 = long) */
736 FALSE
, /* pc_relative */
738 complain_overflow_dont
, /* complain_on_overflow */
739 bfd_elf_generic_reloc
, /* special_function */
740 "R_860_HIGOTOFF", /* name */
741 TRUE
, /* partial_inplace */
742 0xffffffff, /* src_mask */
743 0xffffffff, /* dst_mask */
744 FALSE
), /* pcrel_offset */
747 static unsigned char elf_code_to_howto_index
[R_860_max
+ 1];
749 static reloc_howto_type
*
750 lookup_howto (unsigned int rtype
)
752 static int initialized
= 0;
754 int howto_tbl_size
= (int) (sizeof (elf32_i860_howto_table
)
755 / sizeof (elf32_i860_howto_table
[0]));
760 memset (elf_code_to_howto_index
, 0xff,
761 sizeof (elf_code_to_howto_index
));
762 for (i
= 0; i
< howto_tbl_size
; i
++)
763 elf_code_to_howto_index
[elf32_i860_howto_table
[i
].type
] = i
;
766 BFD_ASSERT (rtype
<= R_860_max
);
767 i
= elf_code_to_howto_index
[rtype
];
768 if (i
>= howto_tbl_size
)
770 return elf32_i860_howto_table
+ i
;
773 /* Given a BFD reloc, return the matching HOWTO structure. */
774 static reloc_howto_type
*
775 elf32_i860_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
776 bfd_reloc_code_real_type code
)
788 case BFD_RELOC_860_COPY
:
791 case BFD_RELOC_860_GLOB_DAT
:
792 rtype
= R_860_GLOB_DAT
;
794 case BFD_RELOC_860_JUMP_SLOT
:
795 rtype
= R_860_JUMP_SLOT
;
797 case BFD_RELOC_860_RELATIVE
:
798 rtype
= R_860_RELATIVE
;
800 case BFD_RELOC_860_PC26
:
803 case BFD_RELOC_860_PLT26
:
806 case BFD_RELOC_860_PC16
:
809 case BFD_RELOC_860_LOW0
:
812 case BFD_RELOC_860_SPLIT0
:
813 rtype
= R_860_SPLIT0
;
815 case BFD_RELOC_860_LOW1
:
818 case BFD_RELOC_860_SPLIT1
:
819 rtype
= R_860_SPLIT1
;
821 case BFD_RELOC_860_LOW2
:
824 case BFD_RELOC_860_SPLIT2
:
825 rtype
= R_860_SPLIT2
;
827 case BFD_RELOC_860_LOW3
:
830 case BFD_RELOC_860_LOGOT0
:
831 rtype
= R_860_LOGOT0
;
833 case BFD_RELOC_860_SPGOT0
:
834 rtype
= R_860_SPGOT0
;
836 case BFD_RELOC_860_LOGOT1
:
837 rtype
= R_860_LOGOT1
;
839 case BFD_RELOC_860_SPGOT1
:
840 rtype
= R_860_SPGOT1
;
842 case BFD_RELOC_860_LOGOTOFF0
:
843 rtype
= R_860_LOGOTOFF0
;
845 case BFD_RELOC_860_SPGOTOFF0
:
846 rtype
= R_860_SPGOTOFF0
;
848 case BFD_RELOC_860_LOGOTOFF1
:
849 rtype
= R_860_LOGOTOFF1
;
851 case BFD_RELOC_860_SPGOTOFF1
:
852 rtype
= R_860_SPGOTOFF1
;
854 case BFD_RELOC_860_LOGOTOFF2
:
855 rtype
= R_860_LOGOTOFF2
;
857 case BFD_RELOC_860_LOGOTOFF3
:
858 rtype
= R_860_LOGOTOFF3
;
860 case BFD_RELOC_860_LOPC
:
863 case BFD_RELOC_860_HIGHADJ
:
864 rtype
= R_860_HIGHADJ
;
866 case BFD_RELOC_860_HAGOT
:
869 case BFD_RELOC_860_HAGOTOFF
:
870 rtype
= R_860_HAGOTOFF
;
872 case BFD_RELOC_860_HAPC
:
875 case BFD_RELOC_860_HIGH
:
878 case BFD_RELOC_860_HIGOT
:
881 case BFD_RELOC_860_HIGOTOFF
:
882 rtype
= R_860_HIGOTOFF
;
888 return lookup_howto (rtype
);
891 static reloc_howto_type
*
892 elf32_i860_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
898 i
< (sizeof (elf32_i860_howto_table
)
899 / sizeof (elf32_i860_howto_table
[0]));
901 if (elf32_i860_howto_table
[i
].name
!= NULL
902 && strcasecmp (elf32_i860_howto_table
[i
].name
, r_name
) == 0)
903 return &elf32_i860_howto_table
[i
];
908 /* Given a ELF reloc, return the matching HOWTO structure. */
910 elf32_i860_info_to_howto_rela (bfd
*abfd ATTRIBUTE_UNUSED
,
912 Elf_Internal_Rela
*elf_reloc
)
915 = lookup_howto ((unsigned) ELF32_R_TYPE (elf_reloc
->r_info
));
918 /* Specialized relocation handler for R_860_SPLITn. These relocations
919 involves a 16-bit field that is split into two contiguous parts. */
920 static bfd_reloc_status_type
921 elf32_i860_relocate_splitn (bfd
*input_bfd
,
922 Elf_Internal_Rela
*rello
,
927 reloc_howto_type
*howto
;
928 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rello
->r_info
));
929 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
932 value
+= rello
->r_addend
;
934 /* Separate the fields and insert. */
935 value
= (((value
& 0xf800) << 5) | (value
& 0x7ff)) & howto
->dst_mask
;
936 insn
= (insn
& ~howto
->dst_mask
) | value
;
938 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
942 /* Specialized relocation handler for R_860_PC16. This relocation
943 involves a 16-bit, PC-relative field that is split into two contiguous
945 static bfd_reloc_status_type
946 elf32_i860_relocate_pc16 (bfd
*input_bfd
,
947 asection
*input_section
,
948 Elf_Internal_Rela
*rello
,
953 reloc_howto_type
*howto
;
954 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rello
->r_info
));
955 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
957 /* Adjust for PC-relative relocation. */
958 value
-= (input_section
->output_section
->vma
959 + input_section
->output_offset
);
960 value
-= rello
->r_offset
;
963 value
+= rello
->r_addend
;
965 /* Adjust the value by 4, then separate the fields and insert. */
966 value
= (value
- 4) >> howto
->rightshift
;
967 value
= (((value
& 0xf800) << 5) | (value
& 0x7ff)) & howto
->dst_mask
;
968 insn
= (insn
& ~howto
->dst_mask
) | value
;
970 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
975 /* Specialized relocation handler for R_860_PC26. This relocation
976 involves a 26-bit, PC-relative field which must be adjusted by 4. */
977 static bfd_reloc_status_type
978 elf32_i860_relocate_pc26 (bfd
*input_bfd
,
979 asection
*input_section
,
980 Elf_Internal_Rela
*rello
,
985 reloc_howto_type
*howto
;
986 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rello
->r_info
));
987 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
989 /* Adjust for PC-relative relocation. */
990 value
-= (input_section
->output_section
->vma
991 + input_section
->output_offset
);
992 value
-= rello
->r_offset
;
995 value
+= rello
->r_addend
;
997 /* Adjust value by 4 and insert the field. */
998 value
= ((value
- 4) >> howto
->rightshift
) & howto
->dst_mask
;
999 insn
= (insn
& ~howto
->dst_mask
) | value
;
1001 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
1002 return bfd_reloc_ok
;
1006 /* Specialized relocation handler for R_860_HIGHADJ. */
1007 static bfd_reloc_status_type
1008 elf32_i860_relocate_highadj (bfd
*input_bfd
,
1009 Elf_Internal_Rela
*rel
,
1015 insn
= bfd_get_32 (input_bfd
, contents
+ rel
->r_offset
);
1017 value
+= rel
->r_addend
;
1019 value
= ((value
>> 16) & 0xffff);
1021 insn
= (insn
& 0xffff0000) | value
;
1023 bfd_put_32 (input_bfd
, insn
, contents
+ rel
->r_offset
);
1024 return bfd_reloc_ok
;
1027 /* Perform a single relocation. By default we use the standard BFD
1028 routines. However, we handle some specially. */
1029 static bfd_reloc_status_type
1030 i860_final_link_relocate (reloc_howto_type
*howto
,
1032 asection
*input_section
,
1034 Elf_Internal_Rela
*rel
,
1037 return _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
1038 contents
, rel
->r_offset
, relocation
,
1042 /* Relocate an i860 ELF section.
1044 This is boiler-plate code copied from fr30.
1046 The RELOCATE_SECTION function is called by the new ELF backend linker
1047 to handle the relocations for a section.
1049 The relocs are always passed as Rela structures; if the section
1050 actually uses Rel structures, the r_addend field will always be
1053 This function is responsible for adjusting the section contents as
1054 necessary, and (if using Rela relocs and generating a relocatable
1055 output file) adjusting the reloc addend as necessary.
1057 This function does not have to worry about setting the reloc
1058 address or the reloc symbol index.
1060 LOCAL_SYMS is a pointer to the swapped in local symbols.
1062 LOCAL_SECTIONS is an array giving the section in the input file
1063 corresponding to the st_shndx field of each local symbol.
1065 The global hash table entry for the global symbols can be found
1066 via elf_sym_hashes (input_bfd).
1068 When generating relocatable output, this function must handle
1069 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
1070 going to be the section symbol corresponding to the output
1071 section, which means that the addend must be adjusted
1074 elf32_i860_relocate_section (bfd
*output_bfd ATTRIBUTE_UNUSED
,
1075 struct bfd_link_info
*info
,
1077 asection
*input_section
,
1079 Elf_Internal_Rela
*relocs
,
1080 Elf_Internal_Sym
*local_syms
,
1081 asection
**local_sections
)
1083 Elf_Internal_Shdr
*symtab_hdr
;
1084 struct elf_link_hash_entry
**sym_hashes
;
1085 Elf_Internal_Rela
*rel
;
1086 Elf_Internal_Rela
*relend
;
1088 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
1089 sym_hashes
= elf_sym_hashes (input_bfd
);
1090 relend
= relocs
+ input_section
->reloc_count
;
1092 for (rel
= relocs
; rel
< relend
; rel
++)
1094 reloc_howto_type
* howto
;
1095 unsigned long r_symndx
;
1096 Elf_Internal_Sym
* sym
;
1098 struct elf_link_hash_entry
* h
;
1100 bfd_reloc_status_type r
;
1101 const char * name
= NULL
;
1104 r_type
= ELF32_R_TYPE (rel
->r_info
);
1105 r_symndx
= ELF32_R_SYM (rel
->r_info
);
1107 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rel
->r_info
));
1112 if (r_symndx
< symtab_hdr
->sh_info
)
1114 sym
= local_syms
+ r_symndx
;
1115 sec
= local_sections
[r_symndx
];
1116 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
1118 name
= bfd_elf_string_from_elf_section
1119 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
1120 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
1124 bfd_boolean unresolved_reloc
, warned
;
1126 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
1127 r_symndx
, symtab_hdr
, sym_hashes
,
1129 unresolved_reloc
, warned
);
1132 if (sec
!= NULL
&& discarded_section (sec
))
1133 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
,
1134 rel
, 1, relend
, howto
, 0, contents
);
1136 if (info
->relocatable
)
1142 r
= i860_final_link_relocate (howto
, input_bfd
, input_section
,
1143 contents
, rel
, relocation
);
1147 r
= elf32_i860_relocate_highadj (input_bfd
, rel
, contents
,
1152 r
= elf32_i860_relocate_pc16 (input_bfd
, input_section
, rel
,
1153 contents
, relocation
);
1157 r
= elf32_i860_relocate_pc26 (input_bfd
, input_section
, rel
,
1158 contents
, relocation
);
1164 r
= elf32_i860_relocate_splitn (input_bfd
, rel
, contents
,
1168 /* We do not yet handle GOT/PLT/Dynamic relocations. */
1170 case R_860_GLOB_DAT
:
1171 case R_860_JUMP_SLOT
:
1172 case R_860_RELATIVE
:
1178 case R_860_LOGOTOFF0
:
1179 case R_860_SPGOTOFF0
:
1180 case R_860_LOGOTOFF1
:
1181 case R_860_SPGOTOFF1
:
1182 case R_860_LOGOTOFF2
:
1183 case R_860_LOGOTOFF3
:
1186 case R_860_HAGOTOFF
:
1189 case R_860_HIGOTOFF
:
1190 r
= bfd_reloc_notsupported
;
1194 if (r
!= bfd_reloc_ok
)
1196 const char * msg
= (const char *) NULL
;
1200 case bfd_reloc_overflow
:
1201 r
= info
->callbacks
->reloc_overflow
1202 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
1203 (bfd_vma
) 0, input_bfd
, input_section
, rel
->r_offset
);
1206 case bfd_reloc_undefined
:
1207 r
= info
->callbacks
->undefined_symbol
1208 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, TRUE
);
1211 case bfd_reloc_outofrange
:
1212 msg
= _("internal error: out of range error");
1215 case bfd_reloc_notsupported
:
1216 msg
= _("internal error: unsupported relocation error");
1219 case bfd_reloc_dangerous
:
1220 msg
= _("internal error: dangerous relocation");
1224 msg
= _("internal error: unknown error");
1229 r
= info
->callbacks
->warning
1230 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
1240 /* Return whether a symbol name implies a local label. SVR4/860 compilers
1241 generate labels of the form ".ep.function_name" to denote the end of a
1242 function prolog. These should be local.
1243 ??? Do any other SVR4 compilers have this convention? If so, this should
1244 be added to the generic routine. */
1246 elf32_i860_is_local_label_name (bfd
*abfd
, const char *name
)
1248 if (name
[0] == '.' && name
[1] == 'e' && name
[2] == 'p' && name
[3] == '.')
1251 return _bfd_elf_is_local_label_name (abfd
, name
);
1254 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1255 #define TARGET_BIG_NAME "elf32-i860"
1256 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1257 #define TARGET_LITTLE_NAME "elf32-i860-little"
1258 #define ELF_ARCH bfd_arch_i860
1259 #define ELF_MACHINE_CODE EM_860
1260 #define ELF_MAXPAGESIZE 4096
1262 #define elf_backend_rela_normal 1
1263 #define elf_info_to_howto_rel NULL
1264 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1265 #define elf_backend_relocate_section elf32_i860_relocate_section
1266 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1267 #define bfd_elf32_bfd_reloc_name_lookup elf32_i860_reloc_name_lookup
1268 #define bfd_elf32_bfd_is_local_label_name elf32_i860_is_local_label_name
1270 #include "elf32-target.h"