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. */
30 /* This howto table is preliminary. */
31 static reloc_howto_type elf32_i860_howto_table
[] =
33 /* This relocation does nothing. */
34 HOWTO (R_860_NONE
, /* type */
36 2, /* size (0 = byte, 1 = short, 2 = long) */
38 FALSE
, /* pc_relative */
40 complain_overflow_bitfield
, /* complain_on_overflow */
41 bfd_elf_generic_reloc
, /* special_function */
42 "R_860_NONE", /* name */
43 FALSE
, /* partial_inplace */
46 FALSE
), /* pcrel_offset */
48 /* A 32-bit absolute relocation. */
49 HOWTO (R_860_32
, /* type */
51 2, /* size (0 = byte, 1 = short, 2 = long) */
53 FALSE
, /* pc_relative */
55 complain_overflow_bitfield
, /* complain_on_overflow */
56 bfd_elf_generic_reloc
, /* special_function */
57 "R_860_32", /* name */
58 FALSE
, /* partial_inplace */
59 0xffffffff, /* src_mask */
60 0xffffffff, /* dst_mask */
61 FALSE
), /* pcrel_offset */
63 HOWTO (R_860_COPY
, /* type */
65 2, /* size (0 = byte, 1 = short, 2 = long) */
67 FALSE
, /* pc_relative */
69 complain_overflow_bitfield
, /* complain_on_overflow */
70 bfd_elf_generic_reloc
, /* special_function */
71 "R_860_COPY", /* name */
72 TRUE
, /* partial_inplace */
73 0xffffffff, /* src_mask */
74 0xffffffff, /* dst_mask */
75 FALSE
), /* pcrel_offset */
77 HOWTO (R_860_GLOB_DAT
, /* type */
79 2, /* size (0 = byte, 1 = short, 2 = long) */
81 FALSE
, /* pc_relative */
83 complain_overflow_bitfield
, /* complain_on_overflow */
84 bfd_elf_generic_reloc
, /* special_function */
85 "R_860_GLOB_DAT", /* name */
86 TRUE
, /* partial_inplace */
87 0xffffffff, /* src_mask */
88 0xffffffff, /* dst_mask */
89 FALSE
), /* pcrel_offset */
91 HOWTO (R_860_JUMP_SLOT
, /* type */
93 2, /* size (0 = byte, 1 = short, 2 = long) */
95 FALSE
, /* pc_relative */
97 complain_overflow_bitfield
, /* complain_on_overflow */
98 bfd_elf_generic_reloc
, /* special_function */
99 "R_860_JUMP_SLOT", /* name */
100 TRUE
, /* partial_inplace */
101 0xffffffff, /* src_mask */
102 0xffffffff, /* dst_mask */
103 FALSE
), /* pcrel_offset */
105 HOWTO (R_860_RELATIVE
, /* type */
107 2, /* size (0 = byte, 1 = short, 2 = long) */
109 FALSE
, /* pc_relative */
111 complain_overflow_bitfield
, /* complain_on_overflow */
112 bfd_elf_generic_reloc
, /* special_function */
113 "R_860_RELATIVE", /* name */
114 TRUE
, /* partial_inplace */
115 0xffffffff, /* src_mask */
116 0xffffffff, /* dst_mask */
117 FALSE
), /* pcrel_offset */
119 /* A 26-bit PC-relative relocation. */
120 HOWTO (R_860_PC26
, /* type */
122 2, /* size (0 = byte, 1 = short, 2 = long) */
124 TRUE
, /* pc_relative */
126 complain_overflow_bitfield
, /* complain_on_overflow */
127 bfd_elf_generic_reloc
, /* special_function */
128 "R_860_PC26", /* name */
129 FALSE
, /* partial_inplace */
130 0x3ffffff, /* src_mask */
131 0x3ffffff, /* dst_mask */
132 TRUE
), /* pcrel_offset */
134 HOWTO (R_860_PLT26
, /* type */
136 2, /* size (0 = byte, 1 = short, 2 = long) */
138 TRUE
, /* pc_relative */
140 complain_overflow_bitfield
, /* complain_on_overflow */
141 bfd_elf_generic_reloc
, /* special_function */
142 "R_860_PLT26", /* name */
143 TRUE
, /* partial_inplace */
144 0xffffffff, /* src_mask */
145 0xffffffff, /* dst_mask */
146 TRUE
), /* pcrel_offset */
148 /* A 16-bit PC-relative relocation. */
149 HOWTO (R_860_PC16
, /* type */
151 2, /* size (0 = byte, 1 = short, 2 = long) */
153 TRUE
, /* pc_relative */
155 complain_overflow_bitfield
, /* complain_on_overflow */
156 bfd_elf_generic_reloc
, /* special_function */
157 "R_860_PC16", /* name */
158 FALSE
, /* partial_inplace */
159 0x1f07ff, /* src_mask */
160 0x1f07ff, /* dst_mask */
161 TRUE
), /* pcrel_offset */
163 HOWTO (R_860_LOW0
, /* type */
165 2, /* size (0 = byte, 1 = short, 2 = long) */
167 FALSE
, /* pc_relative */
169 complain_overflow_dont
, /* complain_on_overflow */
170 bfd_elf_generic_reloc
, /* special_function */
171 "R_860_LOW0", /* name */
172 FALSE
, /* partial_inplace */
173 0xffff, /* src_mask */
174 0xffff, /* dst_mask */
175 FALSE
), /* pcrel_offset */
177 HOWTO (R_860_SPLIT0
, /* type */
179 2, /* size (0 = byte, 1 = short, 2 = long) */
181 FALSE
, /* pc_relative */
183 complain_overflow_dont
, /* complain_on_overflow */
184 bfd_elf_generic_reloc
, /* special_function */
185 "R_860_SPLIT0", /* name */
186 FALSE
, /* partial_inplace */
187 0x1f07ff, /* src_mask */
188 0x1f07ff, /* dst_mask */
189 FALSE
), /* pcrel_offset */
191 HOWTO (R_860_LOW1
, /* type */
193 2, /* size (0 = byte, 1 = short, 2 = long) */
195 FALSE
, /* pc_relative */
197 complain_overflow_dont
, /* complain_on_overflow */
198 bfd_elf_generic_reloc
, /* special_function */
199 "R_860_LOW1", /* name */
200 FALSE
, /* partial_inplace */
201 0xfffe, /* src_mask */
202 0xfffe, /* dst_mask */
203 FALSE
), /* pcrel_offset */
205 HOWTO (R_860_SPLIT1
, /* type */
207 2, /* size (0 = byte, 1 = short, 2 = long) */
209 FALSE
, /* pc_relative */
211 complain_overflow_dont
, /* complain_on_overflow */
212 bfd_elf_generic_reloc
, /* special_function */
213 "R_860_SPLIT1", /* name */
214 FALSE
, /* partial_inplace */
215 0x1f07fe, /* src_mask */
216 0x1f07fe, /* dst_mask */
217 FALSE
), /* pcrel_offset */
219 HOWTO (R_860_LOW2
, /* type */
221 2, /* size (0 = byte, 1 = short, 2 = long) */
223 FALSE
, /* pc_relative */
225 complain_overflow_dont
, /* complain_on_overflow */
226 bfd_elf_generic_reloc
, /* special_function */
227 "R_860_LOW2", /* name */
228 FALSE
, /* partial_inplace */
229 0xfffc, /* src_mask */
230 0xfffc, /* dst_mask */
231 FALSE
), /* pcrel_offset */
233 HOWTO (R_860_SPLIT2
, /* type */
235 2, /* size (0 = byte, 1 = short, 2 = long) */
237 FALSE
, /* pc_relative */
239 complain_overflow_dont
, /* complain_on_overflow */
240 bfd_elf_generic_reloc
, /* special_function */
241 "R_860_SPLIT2", /* name */
242 FALSE
, /* partial_inplace */
243 0x1f07fc, /* src_mask */
244 0x1f07fc, /* dst_mask */
245 FALSE
), /* pcrel_offset */
247 HOWTO (R_860_LOW3
, /* type */
249 2, /* size (0 = byte, 1 = short, 2 = long) */
251 FALSE
, /* pc_relative */
253 complain_overflow_dont
, /* complain_on_overflow */
254 bfd_elf_generic_reloc
, /* special_function */
255 "R_860_LOW3", /* name */
256 FALSE
, /* partial_inplace */
257 0xfff8, /* src_mask */
258 0xfff8, /* dst_mask */
259 FALSE
), /* pcrel_offset */
261 HOWTO (R_860_LOGOT0
, /* type */
263 2, /* size (0 = byte, 1 = short, 2 = long) */
265 FALSE
, /* pc_relative */
267 complain_overflow_dont
, /* complain_on_overflow */
268 bfd_elf_generic_reloc
, /* special_function */
269 "R_860_LOGOT0", /* name */
270 FALSE
, /* partial_inplace */
272 0xffff, /* dst_mask */
273 TRUE
), /* pcrel_offset */
275 HOWTO (R_860_SPGOT0
, /* type */
277 2, /* size (0 = byte, 1 = short, 2 = long) */
279 FALSE
, /* pc_relative */
281 complain_overflow_dont
, /* complain_on_overflow */
282 bfd_elf_generic_reloc
, /* special_function */
283 "R_860_SPGOT0", /* name */
284 FALSE
, /* partial_inplace */
286 0xffff, /* dst_mask */
287 TRUE
), /* pcrel_offset */
289 HOWTO (R_860_LOGOT1
, /* type */
291 2, /* size (0 = byte, 1 = short, 2 = long) */
293 FALSE
, /* pc_relative */
295 complain_overflow_dont
, /* complain_on_overflow */
296 bfd_elf_generic_reloc
, /* special_function */
297 "R_860_LOGOT1", /* name */
298 FALSE
, /* partial_inplace */
300 0xffff, /* dst_mask */
301 TRUE
), /* pcrel_offset */
303 HOWTO (R_860_SPGOT1
, /* type */
305 2, /* size (0 = byte, 1 = short, 2 = long) */
307 FALSE
, /* pc_relative */
309 complain_overflow_dont
, /* complain_on_overflow */
310 bfd_elf_generic_reloc
, /* special_function */
311 "R_860_SPGOT1", /* name */
312 FALSE
, /* partial_inplace */
314 0xffff, /* dst_mask */
315 TRUE
), /* pcrel_offset */
317 HOWTO (R_860_LOGOTOFF0
, /* type */
319 2, /* size (0 = byte, 1 = short, 2 = long) */
321 FALSE
, /* pc_relative */
323 complain_overflow_dont
, /* complain_on_overflow */
324 bfd_elf_generic_reloc
, /* special_function */
325 "R_860_LOGOTOFF0", /* name */
326 TRUE
, /* partial_inplace */
327 0xffffffff, /* src_mask */
328 0xffffffff, /* dst_mask */
329 FALSE
), /* pcrel_offset */
331 HOWTO (R_860_SPGOTOFF0
, /* type */
333 2, /* size (0 = byte, 1 = short, 2 = long) */
335 FALSE
, /* pc_relative */
337 complain_overflow_dont
, /* complain_on_overflow */
338 bfd_elf_generic_reloc
, /* special_function */
339 "R_860_SPGOTOFF0", /* name */
340 TRUE
, /* partial_inplace */
341 0xffffffff, /* src_mask */
342 0xffffffff, /* dst_mask */
343 FALSE
), /* pcrel_offset */
345 HOWTO (R_860_LOGOTOFF1
, /* type */
347 2, /* size (0 = byte, 1 = short, 2 = long) */
349 FALSE
, /* pc_relative */
351 complain_overflow_dont
, /* complain_on_overflow */
352 bfd_elf_generic_reloc
, /* special_function */
353 "R_860_LOGOTOFF1", /* name */
354 TRUE
, /* partial_inplace */
355 0xffffffff, /* src_mask */
356 0xffffffff, /* dst_mask */
357 FALSE
), /* pcrel_offset */
359 HOWTO (R_860_SPGOTOFF1
, /* type */
361 2, /* size (0 = byte, 1 = short, 2 = long) */
363 FALSE
, /* pc_relative */
365 complain_overflow_dont
, /* complain_on_overflow */
366 bfd_elf_generic_reloc
, /* special_function */
367 "R_860_SPGOTOFF1", /* name */
368 TRUE
, /* partial_inplace */
369 0xffffffff, /* src_mask */
370 0xffffffff, /* dst_mask */
371 FALSE
), /* pcrel_offset */
373 HOWTO (R_860_LOGOTOFF2
, /* type */
375 2, /* size (0 = byte, 1 = short, 2 = long) */
377 FALSE
, /* pc_relative */
379 complain_overflow_dont
, /* complain_on_overflow */
380 bfd_elf_generic_reloc
, /* special_function */
381 "R_860_LOGOTOFF2", /* name */
382 TRUE
, /* partial_inplace */
383 0xffffffff, /* src_mask */
384 0xffffffff, /* dst_mask */
385 FALSE
), /* pcrel_offset */
387 HOWTO (R_860_LOGOTOFF3
, /* type */
389 2, /* size (0 = byte, 1 = short, 2 = long) */
391 FALSE
, /* pc_relative */
393 complain_overflow_dont
, /* complain_on_overflow */
394 bfd_elf_generic_reloc
, /* special_function */
395 "R_860_LOGOTOFF3", /* name */
396 TRUE
, /* partial_inplace */
397 0xffffffff, /* src_mask */
398 0xffffffff, /* dst_mask */
399 FALSE
), /* pcrel_offset */
401 HOWTO (R_860_LOPC
, /* type */
403 2, /* size (0 = byte, 1 = short, 2 = long) */
405 TRUE
, /* pc_relative */
407 complain_overflow_bitfield
, /* complain_on_overflow */
408 bfd_elf_generic_reloc
, /* special_function */
409 "R_860_LOPC", /* name */
410 FALSE
, /* partial_inplace */
411 0xffff, /* src_mask */
412 0xffff, /* dst_mask */
413 TRUE
), /* pcrel_offset */
415 HOWTO (R_860_HIGHADJ
, /* type */
417 2, /* size (0 = byte, 1 = short, 2 = long) */
419 FALSE
, /* pc_relative */
421 complain_overflow_dont
, /* complain_on_overflow */
422 bfd_elf_generic_reloc
, /* special_function */
423 "R_860_HIGHADJ", /* name */
424 FALSE
, /* partial_inplace */
425 0xffff, /* src_mask */
426 0xffff, /* dst_mask */
427 FALSE
), /* pcrel_offset */
429 HOWTO (R_860_HAGOT
, /* type */
431 2, /* size (0 = byte, 1 = short, 2 = long) */
433 FALSE
, /* pc_relative */
435 complain_overflow_dont
, /* complain_on_overflow */
436 bfd_elf_generic_reloc
, /* special_function */
437 "R_860_HAGOT", /* name */
438 FALSE
, /* partial_inplace */
440 0xffff, /* dst_mask */
441 TRUE
), /* pcrel_offset */
443 HOWTO (R_860_HAGOTOFF
, /* type */
445 2, /* size (0 = byte, 1 = short, 2 = long) */
447 FALSE
, /* pc_relative */
449 complain_overflow_dont
, /* complain_on_overflow */
450 bfd_elf_generic_reloc
, /* special_function */
451 "R_860_HAGOTOFF", /* name */
452 TRUE
, /* partial_inplace */
453 0xffffffff, /* src_mask */
454 0xffffffff, /* dst_mask */
455 FALSE
), /* pcrel_offset */
457 HOWTO (R_860_HAPC
, /* type */
459 2, /* size (0 = byte, 1 = short, 2 = long) */
461 TRUE
, /* pc_relative */
463 complain_overflow_bitfield
, /* complain_on_overflow */
464 bfd_elf_generic_reloc
, /* special_function */
465 "R_860_HAPC", /* name */
466 FALSE
, /* partial_inplace */
467 0xffff, /* src_mask */
468 0xffff, /* dst_mask */
469 TRUE
), /* pcrel_offset */
471 HOWTO (R_860_HIGH
, /* type */
473 2, /* size (0 = byte, 1 = short, 2 = long) */
475 FALSE
, /* pc_relative */
477 complain_overflow_dont
, /* complain_on_overflow */
478 bfd_elf_generic_reloc
, /* special_function */
479 "R_860_HIGH", /* name */
480 FALSE
, /* partial_inplace */
481 0xffff, /* src_mask */
482 0xffff, /* dst_mask */
483 FALSE
), /* pcrel_offset */
485 HOWTO (R_860_HIGOT
, /* type */
487 2, /* size (0 = byte, 1 = short, 2 = long) */
489 FALSE
, /* pc_relative */
491 complain_overflow_dont
, /* complain_on_overflow */
492 bfd_elf_generic_reloc
, /* special_function */
493 "R_860_HIGOT", /* name */
494 FALSE
, /* partial_inplace */
496 0xffff, /* dst_mask */
497 TRUE
), /* pcrel_offset */
499 HOWTO (R_860_HIGOTOFF
, /* type */
501 2, /* size (0 = byte, 1 = short, 2 = long) */
503 FALSE
, /* pc_relative */
505 complain_overflow_dont
, /* complain_on_overflow */
506 bfd_elf_generic_reloc
, /* special_function */
507 "R_860_HIGOTOFF", /* name */
508 TRUE
, /* partial_inplace */
509 0xffffffff, /* src_mask */
510 0xffffffff, /* dst_mask */
511 FALSE
), /* pcrel_offset */
514 static unsigned char elf_code_to_howto_index
[R_860_max
+ 1];
516 static reloc_howto_type
*
517 lookup_howto (unsigned int rtype
)
519 static int initialized
= 0;
521 int howto_tbl_size
= (int) (sizeof (elf32_i860_howto_table
)
522 / sizeof (elf32_i860_howto_table
[0]));
527 memset (elf_code_to_howto_index
, 0xff,
528 sizeof (elf_code_to_howto_index
));
529 for (i
= 0; i
< howto_tbl_size
; i
++)
530 elf_code_to_howto_index
[elf32_i860_howto_table
[i
].type
] = i
;
533 BFD_ASSERT (rtype
<= R_860_max
);
534 i
= elf_code_to_howto_index
[rtype
];
535 if (i
>= howto_tbl_size
)
537 return elf32_i860_howto_table
+ i
;
540 /* Given a BFD reloc, return the matching HOWTO structure. */
541 static reloc_howto_type
*
542 elf32_i860_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
543 bfd_reloc_code_real_type code
)
555 case BFD_RELOC_860_COPY
:
558 case BFD_RELOC_860_GLOB_DAT
:
559 rtype
= R_860_GLOB_DAT
;
561 case BFD_RELOC_860_JUMP_SLOT
:
562 rtype
= R_860_JUMP_SLOT
;
564 case BFD_RELOC_860_RELATIVE
:
565 rtype
= R_860_RELATIVE
;
567 case BFD_RELOC_860_PC26
:
570 case BFD_RELOC_860_PLT26
:
573 case BFD_RELOC_860_PC16
:
576 case BFD_RELOC_860_LOW0
:
579 case BFD_RELOC_860_SPLIT0
:
580 rtype
= R_860_SPLIT0
;
582 case BFD_RELOC_860_LOW1
:
585 case BFD_RELOC_860_SPLIT1
:
586 rtype
= R_860_SPLIT1
;
588 case BFD_RELOC_860_LOW2
:
591 case BFD_RELOC_860_SPLIT2
:
592 rtype
= R_860_SPLIT2
;
594 case BFD_RELOC_860_LOW3
:
597 case BFD_RELOC_860_LOGOT0
:
598 rtype
= R_860_LOGOT0
;
600 case BFD_RELOC_860_SPGOT0
:
601 rtype
= R_860_SPGOT0
;
603 case BFD_RELOC_860_LOGOT1
:
604 rtype
= R_860_LOGOT1
;
606 case BFD_RELOC_860_SPGOT1
:
607 rtype
= R_860_SPGOT1
;
609 case BFD_RELOC_860_LOGOTOFF0
:
610 rtype
= R_860_LOGOTOFF0
;
612 case BFD_RELOC_860_SPGOTOFF0
:
613 rtype
= R_860_SPGOTOFF0
;
615 case BFD_RELOC_860_LOGOTOFF1
:
616 rtype
= R_860_LOGOTOFF1
;
618 case BFD_RELOC_860_SPGOTOFF1
:
619 rtype
= R_860_SPGOTOFF1
;
621 case BFD_RELOC_860_LOGOTOFF2
:
622 rtype
= R_860_LOGOTOFF2
;
624 case BFD_RELOC_860_LOGOTOFF3
:
625 rtype
= R_860_LOGOTOFF3
;
627 case BFD_RELOC_860_LOPC
:
630 case BFD_RELOC_860_HIGHADJ
:
631 rtype
= R_860_HIGHADJ
;
633 case BFD_RELOC_860_HAGOT
:
636 case BFD_RELOC_860_HAGOTOFF
:
637 rtype
= R_860_HAGOTOFF
;
639 case BFD_RELOC_860_HAPC
:
642 case BFD_RELOC_860_HIGH
:
645 case BFD_RELOC_860_HIGOT
:
648 case BFD_RELOC_860_HIGOTOFF
:
649 rtype
= R_860_HIGOTOFF
;
655 return lookup_howto (rtype
);
658 /* Given a ELF reloc, return the matching HOWTO structure. */
660 elf32_i860_info_to_howto_rela (bfd
*abfd ATTRIBUTE_UNUSED
,
662 Elf_Internal_Rela
*elf_reloc
)
665 = lookup_howto ((unsigned) ELF32_R_TYPE (elf_reloc
->r_info
));
668 /* Specialized relocation handler for R_860_SPLITn. These relocations
669 involves a 16-bit field that is split into two contiguous parts. */
670 static bfd_reloc_status_type
671 elf32_i860_relocate_splitn (bfd
*input_bfd
,
672 Elf_Internal_Rela
*rello
,
677 reloc_howto_type
*howto
;
678 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rello
->r_info
));
679 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
682 value
+= rello
->r_addend
;
684 /* Separate the fields and insert. */
685 value
= (((value
& 0xf800) << 5) | (value
& 0x7ff)) & howto
->dst_mask
;
686 insn
= (insn
& ~howto
->dst_mask
) | value
;
688 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
692 /* Specialized relocation handler for R_860_PC16. This relocation
693 involves a 16-bit, PC-relative field that is split into two contiguous
695 static bfd_reloc_status_type
696 elf32_i860_relocate_pc16 (bfd
*input_bfd
,
697 asection
*input_section
,
698 Elf_Internal_Rela
*rello
,
703 reloc_howto_type
*howto
;
704 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rello
->r_info
));
705 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
707 /* Adjust for PC-relative relocation. */
708 value
-= (input_section
->output_section
->vma
709 + input_section
->output_offset
);
710 value
-= rello
->r_offset
;
713 value
+= rello
->r_addend
;
715 /* Adjust the value by 4, then separate the fields and insert. */
716 value
= (value
- 4) >> howto
->rightshift
;
717 value
= (((value
& 0xf800) << 5) | (value
& 0x7ff)) & howto
->dst_mask
;
718 insn
= (insn
& ~howto
->dst_mask
) | value
;
720 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
725 /* Specialized relocation handler for R_860_PC26. This relocation
726 involves a 26-bit, PC-relative field which must be adjusted by 4. */
727 static bfd_reloc_status_type
728 elf32_i860_relocate_pc26 (bfd
*input_bfd
,
729 asection
*input_section
,
730 Elf_Internal_Rela
*rello
,
735 reloc_howto_type
*howto
;
736 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rello
->r_info
));
737 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
739 /* Adjust for PC-relative relocation. */
740 value
-= (input_section
->output_section
->vma
741 + input_section
->output_offset
);
742 value
-= rello
->r_offset
;
745 value
+= rello
->r_addend
;
747 /* Adjust value by 4 and insert the field. */
748 value
= ((value
- 4) >> howto
->rightshift
) & howto
->dst_mask
;
749 insn
= (insn
& ~howto
->dst_mask
) | value
;
751 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
756 /* Specialized relocation handler for R_860_HIGHADJ. */
757 static bfd_reloc_status_type
758 elf32_i860_relocate_highadj (bfd
*input_bfd
,
759 Elf_Internal_Rela
*rel
,
765 insn
= bfd_get_32 (input_bfd
, contents
+ rel
->r_offset
);
767 value
+= rel
->r_addend
;
769 value
= ((value
>> 16) & 0xffff);
771 insn
= (insn
& 0xffff0000) | value
;
773 bfd_put_32 (input_bfd
, insn
, contents
+ rel
->r_offset
);
777 /* Perform a single relocation. By default we use the standard BFD
778 routines. However, we handle some specially. */
779 static bfd_reloc_status_type
780 i860_final_link_relocate (reloc_howto_type
*howto
,
782 asection
*input_section
,
784 Elf_Internal_Rela
*rel
,
787 return _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
788 contents
, rel
->r_offset
, relocation
,
792 /* Relocate an i860 ELF section.
794 This is boiler-plate code copied from fr30.
796 The RELOCATE_SECTION function is called by the new ELF backend linker
797 to handle the relocations for a section.
799 The relocs are always passed as Rela structures; if the section
800 actually uses Rel structures, the r_addend field will always be
803 This function is responsible for adjusting the section contents as
804 necessary, and (if using Rela relocs and generating a relocatable
805 output file) adjusting the reloc addend as necessary.
807 This function does not have to worry about setting the reloc
808 address or the reloc symbol index.
810 LOCAL_SYMS is a pointer to the swapped in local symbols.
812 LOCAL_SECTIONS is an array giving the section in the input file
813 corresponding to the st_shndx field of each local symbol.
815 The global hash table entry for the global symbols can be found
816 via elf_sym_hashes (input_bfd).
818 When generating relocatable output, this function must handle
819 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
820 going to be the section symbol corresponding to the output
821 section, which means that the addend must be adjusted
824 elf32_i860_relocate_section (bfd
*output_bfd ATTRIBUTE_UNUSED
,
825 struct bfd_link_info
*info
,
827 asection
*input_section
,
829 Elf_Internal_Rela
*relocs
,
830 Elf_Internal_Sym
*local_syms
,
831 asection
**local_sections
)
833 Elf_Internal_Shdr
*symtab_hdr
;
834 struct elf_link_hash_entry
**sym_hashes
;
835 Elf_Internal_Rela
*rel
;
836 Elf_Internal_Rela
*relend
;
838 if (info
->relocatable
)
841 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
842 sym_hashes
= elf_sym_hashes (input_bfd
);
843 relend
= relocs
+ input_section
->reloc_count
;
845 for (rel
= relocs
; rel
< relend
; rel
++)
847 reloc_howto_type
* howto
;
848 unsigned long r_symndx
;
849 Elf_Internal_Sym
* sym
;
851 struct elf_link_hash_entry
* h
;
853 bfd_reloc_status_type r
;
854 const char * name
= NULL
;
857 r_type
= ELF32_R_TYPE (rel
->r_info
);
860 if ( r_type
== R_860_GNU_VTINHERIT
861 || r_type
== R_860_GNU_VTENTRY
)
865 r_symndx
= ELF32_R_SYM (rel
->r_info
);
867 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rel
->r_info
));
872 if (r_symndx
< symtab_hdr
->sh_info
)
874 sym
= local_syms
+ r_symndx
;
875 sec
= local_sections
[r_symndx
];
876 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, sec
, rel
);
878 name
= bfd_elf_string_from_elf_section
879 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
880 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
884 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
886 while (h
->root
.type
== bfd_link_hash_indirect
887 || h
->root
.type
== bfd_link_hash_warning
)
888 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
890 name
= h
->root
.root
.string
;
892 if (h
->root
.type
== bfd_link_hash_defined
893 || h
->root
.type
== bfd_link_hash_defweak
)
895 sec
= h
->root
.u
.def
.section
;
896 relocation
= (h
->root
.u
.def
.value
897 + sec
->output_section
->vma
898 + sec
->output_offset
);
900 else if (h
->root
.type
== bfd_link_hash_undefweak
)
906 if (! ((*info
->callbacks
->undefined_symbol
)
907 (info
, h
->root
.root
.string
, input_bfd
,
908 input_section
, rel
->r_offset
, TRUE
)))
917 r
= i860_final_link_relocate (howto
, input_bfd
, input_section
,
918 contents
, rel
, relocation
);
922 r
= elf32_i860_relocate_highadj (input_bfd
, rel
, contents
,
927 r
= elf32_i860_relocate_pc16 (input_bfd
, input_section
, rel
,
928 contents
, relocation
);
932 r
= elf32_i860_relocate_pc26 (input_bfd
, input_section
, rel
,
933 contents
, relocation
);
939 r
= elf32_i860_relocate_splitn (input_bfd
, rel
, contents
,
943 /* We do not yet handle GOT/PLT/Dynamic relocations. */
946 case R_860_JUMP_SLOT
:
953 case R_860_LOGOTOFF0
:
954 case R_860_SPGOTOFF0
:
955 case R_860_LOGOTOFF1
:
956 case R_860_SPGOTOFF1
:
957 case R_860_LOGOTOFF2
:
958 case R_860_LOGOTOFF3
:
965 r
= bfd_reloc_notsupported
;
969 if (r
!= bfd_reloc_ok
)
971 const char * msg
= (const char *) NULL
;
975 case bfd_reloc_overflow
:
976 r
= info
->callbacks
->reloc_overflow
977 (info
, name
, howto
->name
, (bfd_vma
) 0,
978 input_bfd
, input_section
, rel
->r_offset
);
981 case bfd_reloc_undefined
:
982 r
= info
->callbacks
->undefined_symbol
983 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, TRUE
);
986 case bfd_reloc_outofrange
:
987 msg
= _("internal error: out of range error");
990 case bfd_reloc_notsupported
:
991 msg
= _("internal error: unsupported relocation error");
994 case bfd_reloc_dangerous
:
995 msg
= _("internal error: dangerous relocation");
999 msg
= _("internal error: unknown error");
1004 r
= info
->callbacks
->warning
1005 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
1015 /* Return whether a symbol name implies a local label. SVR4/860 compilers
1016 generate labels of the form ".ep.function_name" to denote the end of a
1017 function prolog. These should be local.
1018 ??? Do any other SVR4 compilers have this convention? If so, this should
1019 be added to the generic routine. */
1021 elf32_i860_is_local_label_name (bfd
*abfd
, const char *name
)
1023 if (name
[0] == '.' && name
[1] == 'e' && name
[2] == 'p' && name
[3] == '.')
1026 return _bfd_elf_is_local_label_name (abfd
, name
);
1029 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1030 #define TARGET_BIG_NAME "elf32-i860"
1031 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1032 #define TARGET_LITTLE_NAME "elf32-i860-little"
1033 #define ELF_ARCH bfd_arch_i860
1034 #define ELF_MACHINE_CODE EM_860
1035 #define ELF_MAXPAGESIZE 4096
1037 #define elf_backend_rela_normal 1
1038 #define elf_info_to_howto_rel NULL
1039 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1040 #define elf_backend_relocate_section elf32_i860_relocate_section
1041 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1042 #define bfd_elf32_bfd_is_local_label_name elf32_i860_is_local_label_name
1044 #include "elf32-target.h"