1 /* Intel i860 specific support for 32-bit ELF.
2 Copyright 1993, 1995, 1999, 2000, 2001, 2002, 2003
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 Derived from bfd_elf_generic_reloc (elf.c) with modifications. */
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
)
40 if (output_bfd
!= NULL
41 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
42 && (! reloc_entry
->howto
->partial_inplace
43 || reloc_entry
->addend
== 0))
45 reloc_entry
->address
+= input_section
->output_offset
;
49 reloc_entry
->addend
-= 4;
50 return bfd_reloc_continue
;
53 /* special_function for R_860_PC16 relocation. */
54 static bfd_reloc_status_type
55 i860_howto_pc16_reloc (bfd
*abfd
,
59 asection
*input_section
,
61 char **error_message ATTRIBUTE_UNUSED
)
67 if (output_bfd
!= NULL
68 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
69 && (! reloc_entry
->howto
->partial_inplace
70 || reloc_entry
->addend
== 0))
72 reloc_entry
->address
+= input_section
->output_offset
;
76 /* Used elf32-mips.c as an example. */
77 if (bfd_is_und_section (symbol
->section
)
78 && output_bfd
== (bfd
*) NULL
)
79 return bfd_reloc_undefined
;
81 if (bfd_is_com_section (symbol
->section
))
84 relocation
= symbol
->value
;
86 relocation
+= symbol
->section
->output_section
->vma
;
87 relocation
+= symbol
->section
->output_offset
;
88 relocation
+= reloc_entry
->addend
;
90 if (reloc_entry
->address
> input_section
->_cooked_size
)
91 return bfd_reloc_outofrange
;
93 /* Adjust for PC-relative relocation. */
94 relocation
-= (input_section
->output_section
->vma
95 + input_section
->output_offset
96 + reloc_entry
->address
99 /* Check for target out of range. */
100 if ((bfd_signed_vma
)relocation
> (0x7fff << 2)
101 || (bfd_signed_vma
)relocation
< (-0x8000 << 2))
102 return bfd_reloc_outofrange
;
104 addr
= (bfd_byte
*) data
+ reloc_entry
->address
;
105 insn
= bfd_get_32 (abfd
, addr
);
107 relocation
>>= reloc_entry
->howto
->rightshift
;
108 relocation
= (((relocation
& 0xf800) << 5) | (relocation
& 0x7ff))
109 & reloc_entry
->howto
->dst_mask
;
110 insn
= (insn
& ~reloc_entry
->howto
->dst_mask
) | relocation
;
112 bfd_put_32 (abfd
, (bfd_vma
) insn
, addr
);
117 /* special_function for R_860_HIGHADJ relocation. */
118 static bfd_reloc_status_type
119 i860_howto_highadj_reloc (bfd
*abfd
,
120 arelent
*reloc_entry
,
123 asection
*input_section
,
125 char **error_message ATTRIBUTE_UNUSED
)
131 if (output_bfd
!= NULL
132 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
133 && (! reloc_entry
->howto
->partial_inplace
134 || reloc_entry
->addend
== 0))
136 reloc_entry
->address
+= input_section
->output_offset
;
140 /* Used elf32-mips.c as an example. */
141 if (bfd_is_und_section (symbol
->section
)
142 && output_bfd
== (bfd
*) NULL
)
143 return bfd_reloc_undefined
;
145 if (bfd_is_com_section (symbol
->section
))
148 relocation
= symbol
->value
;
150 relocation
+= symbol
->section
->output_section
->vma
;
151 relocation
+= symbol
->section
->output_offset
;
152 relocation
+= reloc_entry
->addend
;
153 relocation
+= 0x8000;
155 if (reloc_entry
->address
> input_section
->_cooked_size
)
156 return bfd_reloc_outofrange
;
158 addr
= (bfd_byte
*) data
+ reloc_entry
->address
;
159 insn
= bfd_get_32 (abfd
, addr
);
161 relocation
= ((relocation
>> 16) & 0xffff);
163 insn
= (insn
& 0xffff0000) | relocation
;
165 bfd_put_32 (abfd
, (bfd_vma
) insn
, addr
);
170 /* special_function for R_860_SPLITn relocations. */
171 static bfd_reloc_status_type
172 i860_howto_splitn_reloc (bfd
*abfd
,
173 arelent
*reloc_entry
,
176 asection
*input_section
,
178 char **error_message ATTRIBUTE_UNUSED
)
184 if (output_bfd
!= NULL
185 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
186 && (! reloc_entry
->howto
->partial_inplace
187 || reloc_entry
->addend
== 0))
189 reloc_entry
->address
+= input_section
->output_offset
;
193 /* Used elf32-mips.c as an example. */
194 if (bfd_is_und_section (symbol
->section
)
195 && output_bfd
== (bfd
*) NULL
)
196 return bfd_reloc_undefined
;
198 if (bfd_is_com_section (symbol
->section
))
201 relocation
= symbol
->value
;
203 relocation
+= symbol
->section
->output_section
->vma
;
204 relocation
+= symbol
->section
->output_offset
;
205 relocation
+= reloc_entry
->addend
;
207 if (reloc_entry
->address
> input_section
->_cooked_size
)
208 return bfd_reloc_outofrange
;
210 addr
= (bfd_byte
*) data
+ reloc_entry
->address
;
211 insn
= bfd_get_32 (abfd
, addr
);
213 relocation
= (((relocation
& 0xf800) << 5) | (relocation
& 0x7ff))
214 & reloc_entry
->howto
->dst_mask
;
215 insn
= (insn
& ~reloc_entry
->howto
->dst_mask
) | relocation
;
217 bfd_put_32 (abfd
, (bfd_vma
) insn
, addr
);
222 /* This howto table is preliminary. */
223 static reloc_howto_type elf32_i860_howto_table
[] =
225 /* This relocation does nothing. */
226 HOWTO (R_860_NONE
, /* type */
228 2, /* size (0 = byte, 1 = short, 2 = long) */
230 FALSE
, /* pc_relative */
232 complain_overflow_bitfield
, /* complain_on_overflow */
233 bfd_elf_generic_reloc
, /* special_function */
234 "R_860_NONE", /* name */
235 FALSE
, /* partial_inplace */
238 FALSE
), /* pcrel_offset */
240 /* A 32-bit absolute relocation. */
241 HOWTO (R_860_32
, /* type */
243 2, /* size (0 = byte, 1 = short, 2 = long) */
245 FALSE
, /* pc_relative */
247 complain_overflow_bitfield
, /* complain_on_overflow */
248 bfd_elf_generic_reloc
, /* special_function */
249 "R_860_32", /* name */
250 FALSE
, /* partial_inplace */
251 0xffffffff, /* src_mask */
252 0xffffffff, /* dst_mask */
253 FALSE
), /* pcrel_offset */
255 HOWTO (R_860_COPY
, /* type */
257 2, /* size (0 = byte, 1 = short, 2 = long) */
259 FALSE
, /* pc_relative */
261 complain_overflow_bitfield
, /* complain_on_overflow */
262 bfd_elf_generic_reloc
, /* special_function */
263 "R_860_COPY", /* name */
264 TRUE
, /* partial_inplace */
265 0xffffffff, /* src_mask */
266 0xffffffff, /* dst_mask */
267 FALSE
), /* pcrel_offset */
269 HOWTO (R_860_GLOB_DAT
, /* type */
271 2, /* size (0 = byte, 1 = short, 2 = long) */
273 FALSE
, /* pc_relative */
275 complain_overflow_bitfield
, /* complain_on_overflow */
276 bfd_elf_generic_reloc
, /* special_function */
277 "R_860_GLOB_DAT", /* name */
278 TRUE
, /* partial_inplace */
279 0xffffffff, /* src_mask */
280 0xffffffff, /* dst_mask */
281 FALSE
), /* pcrel_offset */
283 HOWTO (R_860_JUMP_SLOT
, /* type */
285 2, /* size (0 = byte, 1 = short, 2 = long) */
287 FALSE
, /* pc_relative */
289 complain_overflow_bitfield
, /* complain_on_overflow */
290 bfd_elf_generic_reloc
, /* special_function */
291 "R_860_JUMP_SLOT", /* name */
292 TRUE
, /* partial_inplace */
293 0xffffffff, /* src_mask */
294 0xffffffff, /* dst_mask */
295 FALSE
), /* pcrel_offset */
297 HOWTO (R_860_RELATIVE
, /* type */
299 2, /* size (0 = byte, 1 = short, 2 = long) */
301 FALSE
, /* pc_relative */
303 complain_overflow_bitfield
, /* complain_on_overflow */
304 bfd_elf_generic_reloc
, /* special_function */
305 "R_860_RELATIVE", /* name */
306 TRUE
, /* partial_inplace */
307 0xffffffff, /* src_mask */
308 0xffffffff, /* dst_mask */
309 FALSE
), /* pcrel_offset */
311 /* A 26-bit PC-relative relocation. */
312 HOWTO (R_860_PC26
, /* type */
314 2, /* size (0 = byte, 1 = short, 2 = long) */
316 TRUE
, /* pc_relative */
318 complain_overflow_bitfield
, /* complain_on_overflow */
319 i860_howto_pc26_reloc
, /* special_function */
320 "R_860_PC26", /* name */
321 FALSE
, /* partial_inplace */
322 0x3ffffff, /* src_mask */
323 0x3ffffff, /* dst_mask */
324 TRUE
), /* pcrel_offset */
326 HOWTO (R_860_PLT26
, /* type */
328 2, /* size (0 = byte, 1 = short, 2 = long) */
330 TRUE
, /* pc_relative */
332 complain_overflow_bitfield
, /* complain_on_overflow */
333 bfd_elf_generic_reloc
, /* special_function */
334 "R_860_PLT26", /* name */
335 TRUE
, /* partial_inplace */
336 0xffffffff, /* src_mask */
337 0xffffffff, /* dst_mask */
338 TRUE
), /* pcrel_offset */
340 /* A 16-bit PC-relative relocation. */
341 HOWTO (R_860_PC16
, /* type */
343 2, /* size (0 = byte, 1 = short, 2 = long) */
345 TRUE
, /* pc_relative */
347 complain_overflow_bitfield
, /* complain_on_overflow */
348 i860_howto_pc16_reloc
, /* special_function */
349 "R_860_PC16", /* name */
350 FALSE
, /* partial_inplace */
351 0x1f07ff, /* src_mask */
352 0x1f07ff, /* dst_mask */
353 TRUE
), /* pcrel_offset */
355 HOWTO (R_860_LOW0
, /* type */
357 2, /* size (0 = byte, 1 = short, 2 = long) */
359 FALSE
, /* pc_relative */
361 complain_overflow_dont
, /* complain_on_overflow */
362 bfd_elf_generic_reloc
, /* special_function */
363 "R_860_LOW0", /* name */
364 FALSE
, /* partial_inplace */
365 0xffff, /* src_mask */
366 0xffff, /* dst_mask */
367 FALSE
), /* pcrel_offset */
369 HOWTO (R_860_SPLIT0
, /* type */
371 2, /* size (0 = byte, 1 = short, 2 = long) */
373 FALSE
, /* pc_relative */
375 complain_overflow_dont
, /* complain_on_overflow */
376 i860_howto_splitn_reloc
, /* special_function */
377 "R_860_SPLIT0", /* name */
378 FALSE
, /* partial_inplace */
379 0x1f07ff, /* src_mask */
380 0x1f07ff, /* dst_mask */
381 FALSE
), /* pcrel_offset */
383 HOWTO (R_860_LOW1
, /* type */
385 2, /* size (0 = byte, 1 = short, 2 = long) */
387 FALSE
, /* pc_relative */
389 complain_overflow_dont
, /* complain_on_overflow */
390 bfd_elf_generic_reloc
, /* special_function */
391 "R_860_LOW1", /* name */
392 FALSE
, /* partial_inplace */
393 0xfffe, /* src_mask */
394 0xfffe, /* dst_mask */
395 FALSE
), /* pcrel_offset */
397 HOWTO (R_860_SPLIT1
, /* type */
399 2, /* size (0 = byte, 1 = short, 2 = long) */
401 FALSE
, /* pc_relative */
403 complain_overflow_dont
, /* complain_on_overflow */
404 i860_howto_splitn_reloc
, /* special_function */
405 "R_860_SPLIT1", /* name */
406 FALSE
, /* partial_inplace */
407 0x1f07fe, /* src_mask */
408 0x1f07fe, /* dst_mask */
409 FALSE
), /* pcrel_offset */
411 HOWTO (R_860_LOW2
, /* type */
413 2, /* size (0 = byte, 1 = short, 2 = long) */
415 FALSE
, /* pc_relative */
417 complain_overflow_dont
, /* complain_on_overflow */
418 bfd_elf_generic_reloc
, /* special_function */
419 "R_860_LOW2", /* name */
420 FALSE
, /* partial_inplace */
421 0xfffc, /* src_mask */
422 0xfffc, /* dst_mask */
423 FALSE
), /* pcrel_offset */
425 HOWTO (R_860_SPLIT2
, /* type */
427 2, /* size (0 = byte, 1 = short, 2 = long) */
429 FALSE
, /* pc_relative */
431 complain_overflow_dont
, /* complain_on_overflow */
432 i860_howto_splitn_reloc
, /* special_function */
433 "R_860_SPLIT2", /* name */
434 FALSE
, /* partial_inplace */
435 0x1f07fc, /* src_mask */
436 0x1f07fc, /* dst_mask */
437 FALSE
), /* pcrel_offset */
439 HOWTO (R_860_LOW3
, /* type */
441 2, /* size (0 = byte, 1 = short, 2 = long) */
443 FALSE
, /* pc_relative */
445 complain_overflow_dont
, /* complain_on_overflow */
446 bfd_elf_generic_reloc
, /* special_function */
447 "R_860_LOW3", /* name */
448 FALSE
, /* partial_inplace */
449 0xfff8, /* src_mask */
450 0xfff8, /* dst_mask */
451 FALSE
), /* pcrel_offset */
453 HOWTO (R_860_LOGOT0
, /* type */
455 2, /* size (0 = byte, 1 = short, 2 = long) */
457 FALSE
, /* pc_relative */
459 complain_overflow_dont
, /* complain_on_overflow */
460 bfd_elf_generic_reloc
, /* special_function */
461 "R_860_LOGOT0", /* name */
462 FALSE
, /* partial_inplace */
464 0xffff, /* dst_mask */
465 TRUE
), /* pcrel_offset */
467 HOWTO (R_860_SPGOT0
, /* type */
469 2, /* size (0 = byte, 1 = short, 2 = long) */
471 FALSE
, /* pc_relative */
473 complain_overflow_dont
, /* complain_on_overflow */
474 bfd_elf_generic_reloc
, /* special_function */
475 "R_860_SPGOT0", /* name */
476 FALSE
, /* partial_inplace */
478 0xffff, /* dst_mask */
479 TRUE
), /* pcrel_offset */
481 HOWTO (R_860_LOGOT1
, /* type */
483 2, /* size (0 = byte, 1 = short, 2 = long) */
485 FALSE
, /* pc_relative */
487 complain_overflow_dont
, /* complain_on_overflow */
488 bfd_elf_generic_reloc
, /* special_function */
489 "R_860_LOGOT1", /* name */
490 FALSE
, /* partial_inplace */
492 0xffff, /* dst_mask */
493 TRUE
), /* pcrel_offset */
495 HOWTO (R_860_SPGOT1
, /* type */
497 2, /* size (0 = byte, 1 = short, 2 = long) */
499 FALSE
, /* pc_relative */
501 complain_overflow_dont
, /* complain_on_overflow */
502 bfd_elf_generic_reloc
, /* special_function */
503 "R_860_SPGOT1", /* name */
504 FALSE
, /* partial_inplace */
506 0xffff, /* dst_mask */
507 TRUE
), /* pcrel_offset */
509 HOWTO (R_860_LOGOTOFF0
, /* type */
511 2, /* size (0 = byte, 1 = short, 2 = long) */
513 FALSE
, /* pc_relative */
515 complain_overflow_dont
, /* complain_on_overflow */
516 bfd_elf_generic_reloc
, /* special_function */
517 "R_860_LOGOTOFF0", /* name */
518 TRUE
, /* partial_inplace */
519 0xffffffff, /* src_mask */
520 0xffffffff, /* dst_mask */
521 FALSE
), /* pcrel_offset */
523 HOWTO (R_860_SPGOTOFF0
, /* type */
525 2, /* size (0 = byte, 1 = short, 2 = long) */
527 FALSE
, /* pc_relative */
529 complain_overflow_dont
, /* complain_on_overflow */
530 bfd_elf_generic_reloc
, /* special_function */
531 "R_860_SPGOTOFF0", /* name */
532 TRUE
, /* partial_inplace */
533 0xffffffff, /* src_mask */
534 0xffffffff, /* dst_mask */
535 FALSE
), /* pcrel_offset */
537 HOWTO (R_860_LOGOTOFF1
, /* type */
539 2, /* size (0 = byte, 1 = short, 2 = long) */
541 FALSE
, /* pc_relative */
543 complain_overflow_dont
, /* complain_on_overflow */
544 bfd_elf_generic_reloc
, /* special_function */
545 "R_860_LOGOTOFF1", /* name */
546 TRUE
, /* partial_inplace */
547 0xffffffff, /* src_mask */
548 0xffffffff, /* dst_mask */
549 FALSE
), /* pcrel_offset */
551 HOWTO (R_860_SPGOTOFF1
, /* type */
553 2, /* size (0 = byte, 1 = short, 2 = long) */
555 FALSE
, /* pc_relative */
557 complain_overflow_dont
, /* complain_on_overflow */
558 bfd_elf_generic_reloc
, /* special_function */
559 "R_860_SPGOTOFF1", /* name */
560 TRUE
, /* partial_inplace */
561 0xffffffff, /* src_mask */
562 0xffffffff, /* dst_mask */
563 FALSE
), /* pcrel_offset */
565 HOWTO (R_860_LOGOTOFF2
, /* type */
567 2, /* size (0 = byte, 1 = short, 2 = long) */
569 FALSE
, /* pc_relative */
571 complain_overflow_dont
, /* complain_on_overflow */
572 bfd_elf_generic_reloc
, /* special_function */
573 "R_860_LOGOTOFF2", /* name */
574 TRUE
, /* partial_inplace */
575 0xffffffff, /* src_mask */
576 0xffffffff, /* dst_mask */
577 FALSE
), /* pcrel_offset */
579 HOWTO (R_860_LOGOTOFF3
, /* type */
581 2, /* size (0 = byte, 1 = short, 2 = long) */
583 FALSE
, /* pc_relative */
585 complain_overflow_dont
, /* complain_on_overflow */
586 bfd_elf_generic_reloc
, /* special_function */
587 "R_860_LOGOTOFF3", /* name */
588 TRUE
, /* partial_inplace */
589 0xffffffff, /* src_mask */
590 0xffffffff, /* dst_mask */
591 FALSE
), /* pcrel_offset */
593 HOWTO (R_860_LOPC
, /* type */
595 2, /* size (0 = byte, 1 = short, 2 = long) */
597 TRUE
, /* pc_relative */
599 complain_overflow_bitfield
, /* complain_on_overflow */
600 bfd_elf_generic_reloc
, /* special_function */
601 "R_860_LOPC", /* name */
602 FALSE
, /* partial_inplace */
603 0xffff, /* src_mask */
604 0xffff, /* dst_mask */
605 TRUE
), /* pcrel_offset */
607 HOWTO (R_860_HIGHADJ
, /* type */
609 2, /* size (0 = byte, 1 = short, 2 = long) */
611 FALSE
, /* pc_relative */
613 complain_overflow_dont
, /* complain_on_overflow */
614 i860_howto_highadj_reloc
, /* special_function */
615 "R_860_HIGHADJ", /* name */
616 FALSE
, /* partial_inplace */
617 0xffff, /* src_mask */
618 0xffff, /* dst_mask */
619 FALSE
), /* pcrel_offset */
621 HOWTO (R_860_HAGOT
, /* type */
623 2, /* size (0 = byte, 1 = short, 2 = long) */
625 FALSE
, /* pc_relative */
627 complain_overflow_dont
, /* complain_on_overflow */
628 bfd_elf_generic_reloc
, /* special_function */
629 "R_860_HAGOT", /* name */
630 FALSE
, /* partial_inplace */
632 0xffff, /* dst_mask */
633 TRUE
), /* pcrel_offset */
635 HOWTO (R_860_HAGOTOFF
, /* type */
637 2, /* size (0 = byte, 1 = short, 2 = long) */
639 FALSE
, /* pc_relative */
641 complain_overflow_dont
, /* complain_on_overflow */
642 bfd_elf_generic_reloc
, /* special_function */
643 "R_860_HAGOTOFF", /* name */
644 TRUE
, /* partial_inplace */
645 0xffffffff, /* src_mask */
646 0xffffffff, /* dst_mask */
647 FALSE
), /* pcrel_offset */
649 HOWTO (R_860_HAPC
, /* type */
651 2, /* size (0 = byte, 1 = short, 2 = long) */
653 TRUE
, /* pc_relative */
655 complain_overflow_bitfield
, /* complain_on_overflow */
656 bfd_elf_generic_reloc
, /* special_function */
657 "R_860_HAPC", /* name */
658 FALSE
, /* partial_inplace */
659 0xffff, /* src_mask */
660 0xffff, /* dst_mask */
661 TRUE
), /* pcrel_offset */
663 HOWTO (R_860_HIGH
, /* type */
665 2, /* size (0 = byte, 1 = short, 2 = long) */
667 FALSE
, /* pc_relative */
669 complain_overflow_dont
, /* complain_on_overflow */
670 bfd_elf_generic_reloc
, /* special_function */
671 "R_860_HIGH", /* name */
672 FALSE
, /* partial_inplace */
673 0xffff, /* src_mask */
674 0xffff, /* dst_mask */
675 FALSE
), /* pcrel_offset */
677 HOWTO (R_860_HIGOT
, /* type */
679 2, /* size (0 = byte, 1 = short, 2 = long) */
681 FALSE
, /* pc_relative */
683 complain_overflow_dont
, /* complain_on_overflow */
684 bfd_elf_generic_reloc
, /* special_function */
685 "R_860_HIGOT", /* name */
686 FALSE
, /* partial_inplace */
688 0xffff, /* dst_mask */
689 TRUE
), /* pcrel_offset */
691 HOWTO (R_860_HIGOTOFF
, /* type */
693 2, /* size (0 = byte, 1 = short, 2 = long) */
695 FALSE
, /* pc_relative */
697 complain_overflow_dont
, /* complain_on_overflow */
698 bfd_elf_generic_reloc
, /* special_function */
699 "R_860_HIGOTOFF", /* name */
700 TRUE
, /* partial_inplace */
701 0xffffffff, /* src_mask */
702 0xffffffff, /* dst_mask */
703 FALSE
), /* pcrel_offset */
706 static unsigned char elf_code_to_howto_index
[R_860_max
+ 1];
708 static reloc_howto_type
*
709 lookup_howto (unsigned int rtype
)
711 static int initialized
= 0;
713 int howto_tbl_size
= (int) (sizeof (elf32_i860_howto_table
)
714 / sizeof (elf32_i860_howto_table
[0]));
719 memset (elf_code_to_howto_index
, 0xff,
720 sizeof (elf_code_to_howto_index
));
721 for (i
= 0; i
< howto_tbl_size
; i
++)
722 elf_code_to_howto_index
[elf32_i860_howto_table
[i
].type
] = i
;
725 BFD_ASSERT (rtype
<= R_860_max
);
726 i
= elf_code_to_howto_index
[rtype
];
727 if (i
>= howto_tbl_size
)
729 return elf32_i860_howto_table
+ i
;
732 /* Given a BFD reloc, return the matching HOWTO structure. */
733 static reloc_howto_type
*
734 elf32_i860_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
735 bfd_reloc_code_real_type code
)
747 case BFD_RELOC_860_COPY
:
750 case BFD_RELOC_860_GLOB_DAT
:
751 rtype
= R_860_GLOB_DAT
;
753 case BFD_RELOC_860_JUMP_SLOT
:
754 rtype
= R_860_JUMP_SLOT
;
756 case BFD_RELOC_860_RELATIVE
:
757 rtype
= R_860_RELATIVE
;
759 case BFD_RELOC_860_PC26
:
762 case BFD_RELOC_860_PLT26
:
765 case BFD_RELOC_860_PC16
:
768 case BFD_RELOC_860_LOW0
:
771 case BFD_RELOC_860_SPLIT0
:
772 rtype
= R_860_SPLIT0
;
774 case BFD_RELOC_860_LOW1
:
777 case BFD_RELOC_860_SPLIT1
:
778 rtype
= R_860_SPLIT1
;
780 case BFD_RELOC_860_LOW2
:
783 case BFD_RELOC_860_SPLIT2
:
784 rtype
= R_860_SPLIT2
;
786 case BFD_RELOC_860_LOW3
:
789 case BFD_RELOC_860_LOGOT0
:
790 rtype
= R_860_LOGOT0
;
792 case BFD_RELOC_860_SPGOT0
:
793 rtype
= R_860_SPGOT0
;
795 case BFD_RELOC_860_LOGOT1
:
796 rtype
= R_860_LOGOT1
;
798 case BFD_RELOC_860_SPGOT1
:
799 rtype
= R_860_SPGOT1
;
801 case BFD_RELOC_860_LOGOTOFF0
:
802 rtype
= R_860_LOGOTOFF0
;
804 case BFD_RELOC_860_SPGOTOFF0
:
805 rtype
= R_860_SPGOTOFF0
;
807 case BFD_RELOC_860_LOGOTOFF1
:
808 rtype
= R_860_LOGOTOFF1
;
810 case BFD_RELOC_860_SPGOTOFF1
:
811 rtype
= R_860_SPGOTOFF1
;
813 case BFD_RELOC_860_LOGOTOFF2
:
814 rtype
= R_860_LOGOTOFF2
;
816 case BFD_RELOC_860_LOGOTOFF3
:
817 rtype
= R_860_LOGOTOFF3
;
819 case BFD_RELOC_860_LOPC
:
822 case BFD_RELOC_860_HIGHADJ
:
823 rtype
= R_860_HIGHADJ
;
825 case BFD_RELOC_860_HAGOT
:
828 case BFD_RELOC_860_HAGOTOFF
:
829 rtype
= R_860_HAGOTOFF
;
831 case BFD_RELOC_860_HAPC
:
834 case BFD_RELOC_860_HIGH
:
837 case BFD_RELOC_860_HIGOT
:
840 case BFD_RELOC_860_HIGOTOFF
:
841 rtype
= R_860_HIGOTOFF
;
847 return lookup_howto (rtype
);
850 /* Given a ELF reloc, return the matching HOWTO structure. */
852 elf32_i860_info_to_howto_rela (bfd
*abfd ATTRIBUTE_UNUSED
,
854 Elf_Internal_Rela
*elf_reloc
)
857 = lookup_howto ((unsigned) ELF32_R_TYPE (elf_reloc
->r_info
));
860 /* Specialized relocation handler for R_860_SPLITn. These relocations
861 involves a 16-bit field that is split into two contiguous parts. */
862 static bfd_reloc_status_type
863 elf32_i860_relocate_splitn (bfd
*input_bfd
,
864 Elf_Internal_Rela
*rello
,
869 reloc_howto_type
*howto
;
870 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rello
->r_info
));
871 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
874 value
+= rello
->r_addend
;
876 /* Separate the fields and insert. */
877 value
= (((value
& 0xf800) << 5) | (value
& 0x7ff)) & howto
->dst_mask
;
878 insn
= (insn
& ~howto
->dst_mask
) | value
;
880 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
884 /* Specialized relocation handler for R_860_PC16. This relocation
885 involves a 16-bit, PC-relative field that is split into two contiguous
887 static bfd_reloc_status_type
888 elf32_i860_relocate_pc16 (bfd
*input_bfd
,
889 asection
*input_section
,
890 Elf_Internal_Rela
*rello
,
895 reloc_howto_type
*howto
;
896 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rello
->r_info
));
897 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
899 /* Adjust for PC-relative relocation. */
900 value
-= (input_section
->output_section
->vma
901 + input_section
->output_offset
);
902 value
-= rello
->r_offset
;
905 value
+= rello
->r_addend
;
907 /* Adjust the value by 4, then separate the fields and insert. */
908 value
= (value
- 4) >> howto
->rightshift
;
909 value
= (((value
& 0xf800) << 5) | (value
& 0x7ff)) & howto
->dst_mask
;
910 insn
= (insn
& ~howto
->dst_mask
) | value
;
912 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
917 /* Specialized relocation handler for R_860_PC26. This relocation
918 involves a 26-bit, PC-relative field which must be adjusted by 4. */
919 static bfd_reloc_status_type
920 elf32_i860_relocate_pc26 (bfd
*input_bfd
,
921 asection
*input_section
,
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
);
931 /* Adjust for PC-relative relocation. */
932 value
-= (input_section
->output_section
->vma
933 + input_section
->output_offset
);
934 value
-= rello
->r_offset
;
937 value
+= rello
->r_addend
;
939 /* Adjust value by 4 and insert the field. */
940 value
= ((value
- 4) >> howto
->rightshift
) & howto
->dst_mask
;
941 insn
= (insn
& ~howto
->dst_mask
) | value
;
943 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
948 /* Specialized relocation handler for R_860_HIGHADJ. */
949 static bfd_reloc_status_type
950 elf32_i860_relocate_highadj (bfd
*input_bfd
,
951 Elf_Internal_Rela
*rel
,
957 insn
= bfd_get_32 (input_bfd
, contents
+ rel
->r_offset
);
959 value
+= rel
->r_addend
;
961 value
= ((value
>> 16) & 0xffff);
963 insn
= (insn
& 0xffff0000) | value
;
965 bfd_put_32 (input_bfd
, insn
, contents
+ rel
->r_offset
);
969 /* Perform a single relocation. By default we use the standard BFD
970 routines. However, we handle some specially. */
971 static bfd_reloc_status_type
972 i860_final_link_relocate (reloc_howto_type
*howto
,
974 asection
*input_section
,
976 Elf_Internal_Rela
*rel
,
979 return _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
980 contents
, rel
->r_offset
, relocation
,
984 /* Relocate an i860 ELF section.
986 This is boiler-plate code copied from fr30.
988 The RELOCATE_SECTION function is called by the new ELF backend linker
989 to handle the relocations for a section.
991 The relocs are always passed as Rela structures; if the section
992 actually uses Rel structures, the r_addend field will always be
995 This function is responsible for adjusting the section contents as
996 necessary, and (if using Rela relocs and generating a relocatable
997 output file) adjusting the reloc addend as necessary.
999 This function does not have to worry about setting the reloc
1000 address or the reloc symbol index.
1002 LOCAL_SYMS is a pointer to the swapped in local symbols.
1004 LOCAL_SECTIONS is an array giving the section in the input file
1005 corresponding to the st_shndx field of each local symbol.
1007 The global hash table entry for the global symbols can be found
1008 via elf_sym_hashes (input_bfd).
1010 When generating relocatable output, this function must handle
1011 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
1012 going to be the section symbol corresponding to the output
1013 section, which means that the addend must be adjusted
1016 elf32_i860_relocate_section (bfd
*output_bfd ATTRIBUTE_UNUSED
,
1017 struct bfd_link_info
*info
,
1019 asection
*input_section
,
1021 Elf_Internal_Rela
*relocs
,
1022 Elf_Internal_Sym
*local_syms
,
1023 asection
**local_sections
)
1025 Elf_Internal_Shdr
*symtab_hdr
;
1026 struct elf_link_hash_entry
**sym_hashes
;
1027 Elf_Internal_Rela
*rel
;
1028 Elf_Internal_Rela
*relend
;
1030 if (info
->relocatable
)
1033 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
1034 sym_hashes
= elf_sym_hashes (input_bfd
);
1035 relend
= relocs
+ input_section
->reloc_count
;
1037 for (rel
= relocs
; rel
< relend
; rel
++)
1039 reloc_howto_type
* howto
;
1040 unsigned long r_symndx
;
1041 Elf_Internal_Sym
* sym
;
1043 struct elf_link_hash_entry
* h
;
1045 bfd_reloc_status_type r
;
1046 const char * name
= NULL
;
1049 r_type
= ELF32_R_TYPE (rel
->r_info
);
1052 if ( r_type
== R_860_GNU_VTINHERIT
1053 || r_type
== R_860_GNU_VTENTRY
)
1057 r_symndx
= ELF32_R_SYM (rel
->r_info
);
1059 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rel
->r_info
));
1064 if (r_symndx
< symtab_hdr
->sh_info
)
1066 sym
= local_syms
+ r_symndx
;
1067 sec
= local_sections
[r_symndx
];
1068 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, sec
, rel
);
1070 name
= bfd_elf_string_from_elf_section
1071 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
1072 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
1076 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
1078 while (h
->root
.type
== bfd_link_hash_indirect
1079 || h
->root
.type
== bfd_link_hash_warning
)
1080 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
1082 name
= h
->root
.root
.string
;
1084 if (h
->root
.type
== bfd_link_hash_defined
1085 || h
->root
.type
== bfd_link_hash_defweak
)
1087 sec
= h
->root
.u
.def
.section
;
1088 relocation
= (h
->root
.u
.def
.value
1089 + sec
->output_section
->vma
1090 + sec
->output_offset
);
1092 else if (h
->root
.type
== bfd_link_hash_undefweak
)
1098 if (! ((*info
->callbacks
->undefined_symbol
)
1099 (info
, h
->root
.root
.string
, input_bfd
,
1100 input_section
, rel
->r_offset
, TRUE
)))
1109 r
= i860_final_link_relocate (howto
, input_bfd
, input_section
,
1110 contents
, rel
, relocation
);
1114 r
= elf32_i860_relocate_highadj (input_bfd
, rel
, contents
,
1119 r
= elf32_i860_relocate_pc16 (input_bfd
, input_section
, rel
,
1120 contents
, relocation
);
1124 r
= elf32_i860_relocate_pc26 (input_bfd
, input_section
, rel
,
1125 contents
, relocation
);
1131 r
= elf32_i860_relocate_splitn (input_bfd
, rel
, contents
,
1135 /* We do not yet handle GOT/PLT/Dynamic relocations. */
1137 case R_860_GLOB_DAT
:
1138 case R_860_JUMP_SLOT
:
1139 case R_860_RELATIVE
:
1145 case R_860_LOGOTOFF0
:
1146 case R_860_SPGOTOFF0
:
1147 case R_860_LOGOTOFF1
:
1148 case R_860_SPGOTOFF1
:
1149 case R_860_LOGOTOFF2
:
1150 case R_860_LOGOTOFF3
:
1153 case R_860_HAGOTOFF
:
1156 case R_860_HIGOTOFF
:
1157 r
= bfd_reloc_notsupported
;
1161 if (r
!= bfd_reloc_ok
)
1163 const char * msg
= (const char *) NULL
;
1167 case bfd_reloc_overflow
:
1168 r
= info
->callbacks
->reloc_overflow
1169 (info
, name
, howto
->name
, (bfd_vma
) 0,
1170 input_bfd
, input_section
, rel
->r_offset
);
1173 case bfd_reloc_undefined
:
1174 r
= info
->callbacks
->undefined_symbol
1175 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, TRUE
);
1178 case bfd_reloc_outofrange
:
1179 msg
= _("internal error: out of range error");
1182 case bfd_reloc_notsupported
:
1183 msg
= _("internal error: unsupported relocation error");
1186 case bfd_reloc_dangerous
:
1187 msg
= _("internal error: dangerous relocation");
1191 msg
= _("internal error: unknown error");
1196 r
= info
->callbacks
->warning
1197 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
1207 /* Return whether a symbol name implies a local label. SVR4/860 compilers
1208 generate labels of the form ".ep.function_name" to denote the end of a
1209 function prolog. These should be local.
1210 ??? Do any other SVR4 compilers have this convention? If so, this should
1211 be added to the generic routine. */
1213 elf32_i860_is_local_label_name (bfd
*abfd
, const char *name
)
1215 if (name
[0] == '.' && name
[1] == 'e' && name
[2] == 'p' && name
[3] == '.')
1218 return _bfd_elf_is_local_label_name (abfd
, name
);
1221 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1222 #define TARGET_BIG_NAME "elf32-i860"
1223 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1224 #define TARGET_LITTLE_NAME "elf32-i860-little"
1225 #define ELF_ARCH bfd_arch_i860
1226 #define ELF_MACHINE_CODE EM_860
1227 #define ELF_MAXPAGESIZE 4096
1229 #define elf_backend_rela_normal 1
1230 #define elf_info_to_howto_rel NULL
1231 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1232 #define elf_backend_relocate_section elf32_i860_relocate_section
1233 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1234 #define bfd_elf32_bfd_is_local_label_name elf32_i860_is_local_label_name
1236 #include "elf32-target.h"