1 /* Intel i860 specific support for 32-bit ELF.
2 Copyright 1993, 2000 Free Software Foundation, Inc.
4 Full i860 support contributed by Jason Eckhardt <jle@cygnus.com>.
6 This file is part of BFD, the Binary File Descriptor library.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
30 static reloc_howto_type
*lookup_howto
31 PARAMS ((unsigned int));
33 static reloc_howto_type
*elf32_i860_reloc_type_lookup
34 PARAMS ((bfd
*abfd
, bfd_reloc_code_real_type code
));
36 static void elf32_i860_info_to_howto_rela
37 PARAMS ((bfd
*, arelent
*, Elf32_Internal_Rela
*));
39 static bfd_reloc_status_type elf32_i860_relocate_splitn
40 PARAMS ((bfd
*, Elf_Internal_Rela
*, bfd_byte
*, bfd_vma
));
42 static bfd_reloc_status_type elf32_i860_relocate_pc16
43 PARAMS ((bfd
*, asection
*, Elf_Internal_Rela
*, bfd_byte
*, bfd_vma
));
45 static bfd_reloc_status_type elf32_i860_relocate_pc26
46 PARAMS ((bfd
*, asection
*, Elf_Internal_Rela
*, bfd_byte
*, bfd_vma
));
48 static bfd_reloc_status_type elf32_i860_relocate_highadj
49 PARAMS ((bfd
*, Elf_Internal_Rela
*, bfd_byte
*, bfd_vma
));
51 static boolean elf32_i860_relocate_section
52 PARAMS ((bfd
*, struct bfd_link_info
*, bfd
*, asection
*, bfd_byte
*,
53 Elf_Internal_Rela
*, Elf_Internal_Sym
*, asection
**));
55 static bfd_reloc_status_type i860_final_link_relocate
56 PARAMS ((reloc_howto_type
*, bfd
*, asection
*, bfd_byte
*,
57 Elf_Internal_Rela
*, bfd_vma
));
59 static boolean elf32_i860_is_local_label_name
60 PARAMS ((bfd
*, const char *));
64 /* This howto table is preliminary. */
65 static reloc_howto_type elf32_i860_howto_table
[] =
67 /* This relocation does nothing. */
68 HOWTO (R_860_NONE
, /* type */
70 2, /* size (0 = byte, 1 = short, 2 = long) */
72 false, /* pc_relative */
74 complain_overflow_bitfield
, /* complain_on_overflow */
75 bfd_elf_generic_reloc
, /* special_function */
76 "R_860_NONE", /* name */
77 false, /* partial_inplace */
80 false), /* pcrel_offset */
82 /* A 32-bit absolute relocation. */
83 HOWTO (R_860_32
, /* type */
85 2, /* size (0 = byte, 1 = short, 2 = long) */
87 false, /* pc_relative */
89 complain_overflow_bitfield
, /* complain_on_overflow */
90 bfd_elf_generic_reloc
, /* special_function */
91 "R_860_32", /* name */
92 false, /* partial_inplace */
93 0xffffffff, /* src_mask */
94 0xffffffff, /* dst_mask */
95 false), /* pcrel_offset */
97 HOWTO (R_860_COPY
, /* type */
99 2, /* size (0 = byte, 1 = short, 2 = long) */
101 false, /* pc_relative */
103 complain_overflow_bitfield
, /* complain_on_overflow */
104 bfd_elf_generic_reloc
, /* special_function */
105 "R_860_COPY", /* name */
106 true, /* partial_inplace */
107 0xffffffff, /* src_mask */
108 0xffffffff, /* dst_mask */
109 false), /* pcrel_offset */
111 HOWTO (R_860_GLOB_DAT
, /* type */
113 2, /* size (0 = byte, 1 = short, 2 = long) */
115 false, /* pc_relative */
117 complain_overflow_bitfield
, /* complain_on_overflow */
118 bfd_elf_generic_reloc
, /* special_function */
119 "R_860_GLOB_DAT", /* name */
120 true, /* partial_inplace */
121 0xffffffff, /* src_mask */
122 0xffffffff, /* dst_mask */
123 false), /* pcrel_offset */
125 HOWTO (R_860_JUMP_SLOT
, /* type */
127 2, /* size (0 = byte, 1 = short, 2 = long) */
129 false, /* pc_relative */
131 complain_overflow_bitfield
, /* complain_on_overflow */
132 bfd_elf_generic_reloc
, /* special_function */
133 "R_860_JUMP_SLOT", /* name */
134 true, /* partial_inplace */
135 0xffffffff, /* src_mask */
136 0xffffffff, /* dst_mask */
137 false), /* pcrel_offset */
139 HOWTO (R_860_RELATIVE
, /* type */
141 2, /* size (0 = byte, 1 = short, 2 = long) */
143 false, /* pc_relative */
145 complain_overflow_bitfield
, /* complain_on_overflow */
146 bfd_elf_generic_reloc
, /* special_function */
147 "R_860_RELATIVE", /* name */
148 true, /* partial_inplace */
149 0xffffffff, /* src_mask */
150 0xffffffff, /* dst_mask */
151 false), /* pcrel_offset */
153 /* A 26-bit PC-relative relocation. */
154 HOWTO (R_860_PC26
, /* type */
156 2, /* size (0 = byte, 1 = short, 2 = long) */
158 true, /* pc_relative */
160 complain_overflow_bitfield
, /* complain_on_overflow */
161 bfd_elf_generic_reloc
, /* special_function */
162 "R_860_PC26", /* name */
163 false, /* partial_inplace */
164 0x3ffffff, /* src_mask */
165 0x3ffffff, /* dst_mask */
166 true), /* pcrel_offset */
168 HOWTO (R_860_PLT26
, /* type */
170 2, /* size (0 = byte, 1 = short, 2 = long) */
172 true, /* pc_relative */
174 complain_overflow_bitfield
, /* complain_on_overflow */
175 bfd_elf_generic_reloc
, /* special_function */
176 "R_860_PLT26", /* name */
177 true, /* partial_inplace */
178 0xffffffff, /* src_mask */
179 0xffffffff, /* dst_mask */
180 true), /* pcrel_offset */
182 /* A 16-bit PC-relative relocation. */
183 HOWTO (R_860_PC16
, /* type */
185 2, /* size (0 = byte, 1 = short, 2 = long) */
187 true, /* pc_relative */
189 complain_overflow_bitfield
, /* complain_on_overflow */
190 bfd_elf_generic_reloc
, /* special_function */
191 "R_860_PC16", /* name */
192 false, /* partial_inplace */
193 0x1f07ff, /* src_mask */
194 0x1f07ff, /* dst_mask */
195 true), /* pcrel_offset */
197 HOWTO (R_860_LOW0
, /* type */
199 2, /* size (0 = byte, 1 = short, 2 = long) */
201 false, /* pc_relative */
203 complain_overflow_dont
, /* complain_on_overflow */
204 bfd_elf_generic_reloc
, /* special_function */
205 "R_860_LOW0", /* name */
206 false, /* partial_inplace */
207 0xffff, /* src_mask */
208 0xffff, /* dst_mask */
209 false), /* pcrel_offset */
211 HOWTO (R_860_SPLIT0
, /* type */
213 2, /* size (0 = byte, 1 = short, 2 = long) */
215 false, /* pc_relative */
217 complain_overflow_dont
, /* complain_on_overflow */
218 bfd_elf_generic_reloc
, /* special_function */
219 "R_860_SPLIT0", /* name */
220 false, /* partial_inplace */
221 0x1f07ff, /* src_mask */
222 0x1f07ff, /* dst_mask */
223 false), /* pcrel_offset */
225 HOWTO (R_860_LOW1
, /* type */
227 2, /* size (0 = byte, 1 = short, 2 = long) */
229 false, /* pc_relative */
231 complain_overflow_dont
, /* complain_on_overflow */
232 bfd_elf_generic_reloc
, /* special_function */
233 "R_860_LOW1", /* name */
234 false, /* partial_inplace */
235 0xfffe, /* src_mask */
236 0xfffe, /* dst_mask */
237 false), /* pcrel_offset */
239 HOWTO (R_860_SPLIT1
, /* type */
241 2, /* size (0 = byte, 1 = short, 2 = long) */
243 false, /* pc_relative */
245 complain_overflow_dont
, /* complain_on_overflow */
246 bfd_elf_generic_reloc
, /* special_function */
247 "R_860_SPLIT1", /* name */
248 false, /* partial_inplace */
249 0x1f07fe, /* src_mask */
250 0x1f07fe, /* dst_mask */
251 false), /* pcrel_offset */
253 HOWTO (R_860_LOW2
, /* type */
255 2, /* size (0 = byte, 1 = short, 2 = long) */
257 false, /* pc_relative */
259 complain_overflow_dont
, /* complain_on_overflow */
260 bfd_elf_generic_reloc
, /* special_function */
261 "R_860_LOW2", /* name */
262 false, /* partial_inplace */
263 0xfffc, /* src_mask */
264 0xfffc, /* dst_mask */
265 false), /* pcrel_offset */
267 HOWTO (R_860_SPLIT2
, /* type */
269 2, /* size (0 = byte, 1 = short, 2 = long) */
271 false, /* pc_relative */
273 complain_overflow_dont
, /* complain_on_overflow */
274 bfd_elf_generic_reloc
, /* special_function */
275 "R_860_SPLIT2", /* name */
276 false, /* partial_inplace */
277 0x1f07fc, /* src_mask */
278 0x1f07fc, /* dst_mask */
279 false), /* pcrel_offset */
281 HOWTO (R_860_LOW3
, /* type */
283 2, /* size (0 = byte, 1 = short, 2 = long) */
285 false, /* pc_relative */
287 complain_overflow_dont
, /* complain_on_overflow */
288 bfd_elf_generic_reloc
, /* special_function */
289 "R_860_LOW3", /* name */
290 false, /* partial_inplace */
291 0xfff8, /* src_mask */
292 0xfff8, /* dst_mask */
293 false), /* pcrel_offset */
295 HOWTO (R_860_LOGOT0
, /* type */
297 2, /* size (0 = byte, 1 = short, 2 = long) */
299 false, /* pc_relative */
301 complain_overflow_dont
, /* complain_on_overflow */
302 bfd_elf_generic_reloc
, /* special_function */
303 "R_860_LOGOT0", /* name */
304 false, /* partial_inplace */
306 0xffff, /* dst_mask */
307 true), /* pcrel_offset */
309 HOWTO (R_860_SPGOT0
, /* type */
311 2, /* size (0 = byte, 1 = short, 2 = long) */
313 false, /* pc_relative */
315 complain_overflow_dont
, /* complain_on_overflow */
316 bfd_elf_generic_reloc
, /* special_function */
317 "R_860_SPGOT0", /* name */
318 false, /* partial_inplace */
320 0xffff, /* dst_mask */
321 true), /* pcrel_offset */
323 HOWTO (R_860_LOGOT1
, /* type */
325 2, /* size (0 = byte, 1 = short, 2 = long) */
327 false, /* pc_relative */
329 complain_overflow_dont
, /* complain_on_overflow */
330 bfd_elf_generic_reloc
, /* special_function */
331 "R_860_LOGOT1", /* name */
332 false, /* partial_inplace */
334 0xffff, /* dst_mask */
335 true), /* pcrel_offset */
337 HOWTO (R_860_SPGOT1
, /* type */
339 2, /* size (0 = byte, 1 = short, 2 = long) */
341 false, /* pc_relative */
343 complain_overflow_dont
, /* complain_on_overflow */
344 bfd_elf_generic_reloc
, /* special_function */
345 "R_860_SPGOT1", /* name */
346 false, /* partial_inplace */
348 0xffff, /* dst_mask */
349 true), /* pcrel_offset */
351 HOWTO (R_860_LOGOTOFF0
, /* type */
353 2, /* size (0 = byte, 1 = short, 2 = long) */
355 false, /* pc_relative */
357 complain_overflow_dont
, /* complain_on_overflow */
358 bfd_elf_generic_reloc
, /* special_function */
359 "R_860_LOGOTOFF0", /* name */
360 true, /* partial_inplace */
361 0xffffffff, /* src_mask */
362 0xffffffff, /* dst_mask */
363 false), /* pcrel_offset */
365 HOWTO (R_860_SPGOTOFF0
, /* type */
367 2, /* size (0 = byte, 1 = short, 2 = long) */
369 false, /* pc_relative */
371 complain_overflow_dont
, /* complain_on_overflow */
372 bfd_elf_generic_reloc
, /* special_function */
373 "R_860_SPGOTOFF0", /* name */
374 true, /* partial_inplace */
375 0xffffffff, /* src_mask */
376 0xffffffff, /* dst_mask */
377 false), /* pcrel_offset */
379 HOWTO (R_860_LOGOTOFF1
, /* type */
381 2, /* size (0 = byte, 1 = short, 2 = long) */
383 false, /* pc_relative */
385 complain_overflow_dont
, /* complain_on_overflow */
386 bfd_elf_generic_reloc
, /* special_function */
387 "R_860_LOGOTOFF1", /* name */
388 true, /* partial_inplace */
389 0xffffffff, /* src_mask */
390 0xffffffff, /* dst_mask */
391 false), /* pcrel_offset */
393 HOWTO (R_860_SPGOTOFF1
, /* type */
395 2, /* size (0 = byte, 1 = short, 2 = long) */
397 false, /* pc_relative */
399 complain_overflow_dont
, /* complain_on_overflow */
400 bfd_elf_generic_reloc
, /* special_function */
401 "R_860_SPGOTOFF1", /* name */
402 true, /* partial_inplace */
403 0xffffffff, /* src_mask */
404 0xffffffff, /* dst_mask */
405 false), /* pcrel_offset */
407 HOWTO (R_860_LOGOTOFF2
, /* type */
409 2, /* size (0 = byte, 1 = short, 2 = long) */
411 false, /* pc_relative */
413 complain_overflow_dont
, /* complain_on_overflow */
414 bfd_elf_generic_reloc
, /* special_function */
415 "R_860_LOGOTOFF2", /* name */
416 true, /* partial_inplace */
417 0xffffffff, /* src_mask */
418 0xffffffff, /* dst_mask */
419 false), /* pcrel_offset */
421 HOWTO (R_860_LOGOTOFF3
, /* type */
423 2, /* size (0 = byte, 1 = short, 2 = long) */
425 false, /* pc_relative */
427 complain_overflow_dont
, /* complain_on_overflow */
428 bfd_elf_generic_reloc
, /* special_function */
429 "R_860_LOGOTOFF3", /* name */
430 true, /* partial_inplace */
431 0xffffffff, /* src_mask */
432 0xffffffff, /* dst_mask */
433 false), /* pcrel_offset */
435 HOWTO (R_860_LOPC
, /* type */
437 2, /* size (0 = byte, 1 = short, 2 = long) */
439 true, /* pc_relative */
441 complain_overflow_bitfield
, /* complain_on_overflow */
442 bfd_elf_generic_reloc
, /* special_function */
443 "R_860_LOPC", /* name */
444 false, /* partial_inplace */
445 0xffff, /* src_mask */
446 0xffff, /* dst_mask */
447 true), /* pcrel_offset */
449 HOWTO (R_860_HIGHADJ
, /* type */
451 2, /* size (0 = byte, 1 = short, 2 = long) */
453 false, /* pc_relative */
455 complain_overflow_dont
, /* complain_on_overflow */
456 bfd_elf_generic_reloc
, /* special_function */
457 "R_860_HIGHADJ", /* name */
458 false, /* partial_inplace */
459 0xffff, /* src_mask */
460 0xffff, /* dst_mask */
461 false), /* pcrel_offset */
463 HOWTO (R_860_HAGOT
, /* type */
465 2, /* size (0 = byte, 1 = short, 2 = long) */
467 false, /* pc_relative */
469 complain_overflow_dont
, /* complain_on_overflow */
470 bfd_elf_generic_reloc
, /* special_function */
471 "R_860_HAGOT", /* name */
472 false, /* partial_inplace */
474 0xffff, /* dst_mask */
475 true), /* pcrel_offset */
477 HOWTO (R_860_HAGOTOFF
, /* type */
479 2, /* size (0 = byte, 1 = short, 2 = long) */
481 false, /* pc_relative */
483 complain_overflow_dont
, /* complain_on_overflow */
484 bfd_elf_generic_reloc
, /* special_function */
485 "R_860_HAGOTOFF", /* name */
486 true, /* partial_inplace */
487 0xffffffff, /* src_mask */
488 0xffffffff, /* dst_mask */
489 false), /* pcrel_offset */
491 HOWTO (R_860_HAPC
, /* type */
493 2, /* size (0 = byte, 1 = short, 2 = long) */
495 true, /* pc_relative */
497 complain_overflow_bitfield
, /* complain_on_overflow */
498 bfd_elf_generic_reloc
, /* special_function */
499 "R_860_HAPC", /* name */
500 false, /* partial_inplace */
501 0xffff, /* src_mask */
502 0xffff, /* dst_mask */
503 true), /* pcrel_offset */
505 HOWTO (R_860_HIGH
, /* type */
507 2, /* size (0 = byte, 1 = short, 2 = long) */
509 false, /* pc_relative */
511 complain_overflow_dont
, /* complain_on_overflow */
512 bfd_elf_generic_reloc
, /* special_function */
513 "R_860_HIGH", /* name */
514 false, /* partial_inplace */
515 0xffff, /* src_mask */
516 0xffff, /* dst_mask */
517 false), /* pcrel_offset */
519 HOWTO (R_860_HIGOT
, /* type */
521 2, /* size (0 = byte, 1 = short, 2 = long) */
523 false, /* pc_relative */
525 complain_overflow_dont
, /* complain_on_overflow */
526 bfd_elf_generic_reloc
, /* special_function */
527 "R_860_HIGOT", /* name */
528 false, /* partial_inplace */
530 0xffff, /* dst_mask */
531 true), /* pcrel_offset */
533 HOWTO (R_860_HIGOTOFF
, /* type */
535 2, /* size (0 = byte, 1 = short, 2 = long) */
537 false, /* pc_relative */
539 complain_overflow_dont
, /* complain_on_overflow */
540 bfd_elf_generic_reloc
, /* special_function */
541 "R_860_HIGOTOFF", /* name */
542 true, /* partial_inplace */
543 0xffffffff, /* src_mask */
544 0xffffffff, /* dst_mask */
545 false), /* pcrel_offset */
549 static unsigned char elf_code_to_howto_index
[R_860_max
+ 1];
551 static reloc_howto_type
*
555 static int initialized
= 0;
557 int howto_tbl_size
= (int) (sizeof (elf32_i860_howto_table
)
558 / sizeof (elf32_i860_howto_table
[0]));
563 memset (elf_code_to_howto_index
, 0xff,
564 sizeof (elf_code_to_howto_index
));
565 for (i
= 0; i
< howto_tbl_size
; i
++)
566 elf_code_to_howto_index
[elf32_i860_howto_table
[i
].type
] = i
;
569 BFD_ASSERT (rtype
<= R_860_max
);
570 i
= elf_code_to_howto_index
[rtype
];
571 if (i
>= howto_tbl_size
)
573 return elf32_i860_howto_table
+ i
;
577 /* Given a BFD reloc, return the matching HOWTO structure. */
578 static reloc_howto_type
*
579 elf32_i860_reloc_type_lookup (abfd
, code
)
580 bfd
* abfd ATTRIBUTE_UNUSED
;
581 bfd_reloc_code_real_type code
;
593 case BFD_RELOC_860_COPY
:
596 case BFD_RELOC_860_GLOB_DAT
:
597 rtype
= R_860_GLOB_DAT
;
599 case BFD_RELOC_860_JUMP_SLOT
:
600 rtype
= R_860_JUMP_SLOT
;
602 case BFD_RELOC_860_RELATIVE
:
603 rtype
= R_860_RELATIVE
;
605 case BFD_RELOC_860_PC26
:
608 case BFD_RELOC_860_PLT26
:
611 case BFD_RELOC_860_PC16
:
614 case BFD_RELOC_860_LOW0
:
617 case BFD_RELOC_860_SPLIT0
:
618 rtype
= R_860_SPLIT0
;
620 case BFD_RELOC_860_LOW1
:
623 case BFD_RELOC_860_SPLIT1
:
624 rtype
= R_860_SPLIT1
;
626 case BFD_RELOC_860_LOW2
:
629 case BFD_RELOC_860_SPLIT2
:
630 rtype
= R_860_SPLIT2
;
632 case BFD_RELOC_860_LOW3
:
635 case BFD_RELOC_860_LOGOT0
:
636 rtype
= R_860_LOGOT0
;
638 case BFD_RELOC_860_SPGOT0
:
639 rtype
= R_860_SPGOT0
;
641 case BFD_RELOC_860_LOGOT1
:
642 rtype
= R_860_LOGOT1
;
644 case BFD_RELOC_860_SPGOT1
:
645 rtype
= R_860_SPGOT1
;
647 case BFD_RELOC_860_LOGOTOFF0
:
648 rtype
= R_860_LOGOTOFF0
;
650 case BFD_RELOC_860_SPGOTOFF0
:
651 rtype
= R_860_SPGOTOFF0
;
653 case BFD_RELOC_860_LOGOTOFF1
:
654 rtype
= R_860_LOGOTOFF1
;
656 case BFD_RELOC_860_SPGOTOFF1
:
657 rtype
= R_860_SPGOTOFF1
;
659 case BFD_RELOC_860_LOGOTOFF2
:
660 rtype
= R_860_LOGOTOFF2
;
662 case BFD_RELOC_860_LOGOTOFF3
:
663 rtype
= R_860_LOGOTOFF3
;
665 case BFD_RELOC_860_LOPC
:
668 case BFD_RELOC_860_HIGHADJ
:
669 rtype
= R_860_HIGHADJ
;
671 case BFD_RELOC_860_HAGOT
:
674 case BFD_RELOC_860_HAGOTOFF
:
675 rtype
= R_860_HAGOTOFF
;
677 case BFD_RELOC_860_HAPC
:
680 case BFD_RELOC_860_HIGH
:
683 case BFD_RELOC_860_HIGOT
:
686 case BFD_RELOC_860_HIGOTOFF
:
687 rtype
= R_860_HIGOTOFF
;
693 return lookup_howto (rtype
);
697 /* Given a ELF reloc, return the matching HOWTO structure. */
699 elf32_i860_info_to_howto_rela (abfd
, bfd_reloc
, elf_reloc
)
700 bfd
*abfd ATTRIBUTE_UNUSED
;
702 Elf64_Internal_Rela
*elf_reloc
;
704 bfd_reloc
->howto
= lookup_howto (ELF32_R_TYPE (elf_reloc
->r_info
));
709 /* Specialized relocation handler for R_860_SPLITn. These relocations
710 involves a 16-bit field that is split into two contiguous parts. */
711 static bfd_reloc_status_type
712 elf32_i860_relocate_splitn (input_bfd
, rello
, contents
, value
)
714 Elf_Internal_Rela
*rello
;
719 reloc_howto_type
*howto
;
720 howto
= lookup_howto (ELF32_R_TYPE (rello
->r_info
));
721 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
724 value
+= rello
->r_addend
;
726 /* Separate the fields and insert. */
727 value
= (((value
& 0xf8) << 5) | (value
& 0x7ff)) & howto
->dst_mask
;
728 insn
= (insn
& ~howto
->dst_mask
) | value
;
730 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
735 /* Specialized relocation handler for R_860_PC16. This relocation
736 involves a 16-bit, PC-relative field that is split into two contiguous
738 static bfd_reloc_status_type
739 elf32_i860_relocate_pc16 (input_bfd
, input_section
, rello
, contents
, value
)
741 asection
*input_section
;
742 Elf_Internal_Rela
*rello
;
747 reloc_howto_type
*howto
;
748 howto
= lookup_howto (ELF32_R_TYPE (rello
->r_info
));
749 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
751 /* Adjust for PC-relative relocation. */
752 value
-= (input_section
->output_section
->vma
753 + input_section
->output_offset
);
754 value
-= rello
->r_offset
;
757 value
+= rello
->r_addend
;
759 /* Separate the fields and insert. */
760 value
= (((value
& 0xf8) << 5) | (value
& 0x7ff)) & howto
->dst_mask
;
761 insn
= (insn
& ~howto
->dst_mask
) | value
;
763 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
769 /* Specialized relocation handler for R_860_PC26. This relocation
770 involves a 26-bit, PC-relative field which must be adjusted by 4. */
771 static bfd_reloc_status_type
772 elf32_i860_relocate_pc26 (input_bfd
, input_section
, rello
, contents
, value
)
774 asection
*input_section
;
775 Elf_Internal_Rela
*rello
;
780 reloc_howto_type
*howto
;
781 howto
= lookup_howto (ELF32_R_TYPE (rello
->r_info
));
782 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
784 /* Adjust for PC-relative relocation. */
785 value
-= (input_section
->output_section
->vma
786 + input_section
->output_offset
);
787 value
-= rello
->r_offset
;
790 value
+= rello
->r_addend
;
792 /* Adjust value by 4 and insert the field. */
793 value
= ((value
- 4) >> howto
->rightshift
) & howto
->dst_mask
;
794 insn
= (insn
& ~howto
->dst_mask
) | value
;
796 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
802 /* Specialized relocation handler for R_860_HIGHADJ. */
803 static bfd_reloc_status_type
804 elf32_i860_relocate_highadj (input_bfd
, rel
, contents
, value
)
806 Elf_Internal_Rela
*rel
;
812 insn
= bfd_get_32 (input_bfd
, contents
+ rel
->r_offset
);
814 value
+= ((rel
->r_addend
& 0x8000) << 1);
815 value
+= rel
->r_addend
;
816 value
= ((value
>> 16) & 0xffff);
818 insn
= (insn
& 0xffff0000) | value
;
820 bfd_put_32 (input_bfd
, insn
, contents
+ rel
->r_offset
);
825 /* Perform a single relocation. By default we use the standard BFD
826 routines. However, we handle some specially. */
827 static bfd_reloc_status_type
828 i860_final_link_relocate (howto
, input_bfd
, input_section
, contents
, rel
, relocation
)
829 reloc_howto_type
* howto
;
831 asection
* input_section
;
833 Elf_Internal_Rela
* rel
;
836 return _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
837 contents
, rel
->r_offset
, relocation
,
842 /* Relocate an i860 ELF section.
844 This is boiler-plate code copied from fr30.
845 There is some attempt to make this function usable for many architectures,
846 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
847 if only to serve as a learning tool.
849 The RELOCATE_SECTION function is called by the new ELF backend linker
850 to handle the relocations for a section.
852 The relocs are always passed as Rela structures; if the section
853 actually uses Rel structures, the r_addend field will always be
856 This function is responsible for adjusting the section contents as
857 necessary, and (if using Rela relocs and generating a relocateable
858 output file) adjusting the reloc addend as necessary.
860 This function does not have to worry about setting the reloc
861 address or the reloc symbol index.
863 LOCAL_SYMS is a pointer to the swapped in local symbols.
865 LOCAL_SECTIONS is an array giving the section in the input file
866 corresponding to the st_shndx field of each local symbol.
868 The global hash table entry for the global symbols can be found
869 via elf_sym_hashes (input_bfd).
871 When generating relocateable output, this function must handle
872 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
873 going to be the section symbol corresponding to the output
874 section, which means that the addend must be adjusted
877 elf32_i860_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
878 contents
, relocs
, local_syms
, local_sections
)
879 bfd
* output_bfd ATTRIBUTE_UNUSED
;
880 struct bfd_link_info
* info
;
882 asection
* input_section
;
884 Elf_Internal_Rela
* relocs
;
885 Elf_Internal_Sym
* local_syms
;
886 asection
** local_sections
;
888 Elf_Internal_Shdr
* symtab_hdr
;
889 struct elf_link_hash_entry
** sym_hashes
;
890 Elf_Internal_Rela
* rel
;
891 Elf_Internal_Rela
* relend
;
893 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
894 sym_hashes
= elf_sym_hashes (input_bfd
);
895 relend
= relocs
+ input_section
->reloc_count
;
897 for (rel
= relocs
; rel
< relend
; rel
++)
899 reloc_howto_type
* howto
;
900 unsigned long r_symndx
;
901 Elf_Internal_Sym
* sym
;
903 struct elf_link_hash_entry
* h
;
905 bfd_reloc_status_type r
;
906 const char * name
= NULL
;
909 r_type
= ELF32_R_TYPE (rel
->r_info
);
912 if ( r_type
== R_860_GNU_VTINHERIT
913 || r_type
== R_860_GNU_VTENTRY
)
917 r_symndx
= ELF32_R_SYM (rel
->r_info
);
919 if (info
->relocateable
)
921 /* This is a relocateable link. We don't have to change
922 anything, unless the reloc is against a section symbol,
923 in which case we have to adjust according to where the
924 section symbol winds up in the output section. */
925 if (r_symndx
< symtab_hdr
->sh_info
)
927 sym
= local_syms
+ r_symndx
;
929 if (ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
931 sec
= local_sections
[r_symndx
];
932 rel
->r_addend
+= sec
->output_offset
+ sym
->st_value
;
939 /* This is a final link. */
940 howto
= lookup_howto (ELF32_R_TYPE (rel
->r_info
));
945 if (r_symndx
< symtab_hdr
->sh_info
)
947 sym
= local_syms
+ r_symndx
;
948 sec
= local_sections
[r_symndx
];
949 relocation
= (sec
->output_section
->vma
953 name
= bfd_elf_string_from_elf_section
954 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
955 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
959 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
961 while (h
->root
.type
== bfd_link_hash_indirect
962 || h
->root
.type
== bfd_link_hash_warning
)
963 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
965 name
= h
->root
.root
.string
;
967 if (h
->root
.type
== bfd_link_hash_defined
968 || h
->root
.type
== bfd_link_hash_defweak
)
970 sec
= h
->root
.u
.def
.section
;
971 relocation
= (h
->root
.u
.def
.value
972 + sec
->output_section
->vma
973 + sec
->output_offset
);
975 else if (h
->root
.type
== bfd_link_hash_undefweak
)
981 if (! ((*info
->callbacks
->undefined_symbol
)
982 (info
, h
->root
.root
.string
, input_bfd
,
983 input_section
, rel
->r_offset
, true)))
992 r
= i860_final_link_relocate (howto
, input_bfd
, input_section
,
993 contents
, rel
, relocation
);
997 r
= elf32_i860_relocate_highadj (input_bfd
, rel
, contents
,
1002 r
= elf32_i860_relocate_pc16 (input_bfd
, input_section
, rel
,
1003 contents
, relocation
);
1007 r
= elf32_i860_relocate_pc26 (input_bfd
, input_section
, rel
,
1008 contents
, relocation
);
1014 r
= elf32_i860_relocate_splitn (input_bfd
, rel
, contents
,
1018 /* We do not yet handle GOT/PLT/Dynamic relocations. */
1020 case R_860_GLOB_DAT
:
1021 case R_860_JUMP_SLOT
:
1022 case R_860_RELATIVE
:
1028 case R_860_LOGOTOFF0
:
1029 case R_860_SPGOTOFF0
:
1030 case R_860_LOGOTOFF1
:
1031 case R_860_SPGOTOFF1
:
1032 case R_860_LOGOTOFF2
:
1033 case R_860_LOGOTOFF3
:
1036 case R_860_HAGOTOFF
:
1039 case R_860_HIGOTOFF
:
1040 r
= bfd_reloc_notsupported
;
1044 if (r
!= bfd_reloc_ok
)
1046 const char * msg
= (const char *) NULL
;
1050 case bfd_reloc_overflow
:
1051 r
= info
->callbacks
->reloc_overflow
1052 (info
, name
, howto
->name
, (bfd_vma
) 0,
1053 input_bfd
, input_section
, rel
->r_offset
);
1056 case bfd_reloc_undefined
:
1057 r
= info
->callbacks
->undefined_symbol
1058 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, true);
1061 case bfd_reloc_outofrange
:
1062 msg
= _("internal error: out of range error");
1065 case bfd_reloc_notsupported
:
1066 msg
= _("internal error: unsupported relocation error");
1069 case bfd_reloc_dangerous
:
1070 msg
= _("internal error: dangerous relocation");
1074 msg
= _("internal error: unknown error");
1079 r
= info
->callbacks
->warning
1080 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
1091 /* Return whether a symbol name implies a local label. SVR4/860 compilers
1092 generate labels of the form ".ep.function_name" to denote the end of a
1093 function prolog. These should be local.
1094 ??? Do any other SVR4 compilers have this convention? If so, this should
1095 be added to the generic routine. */
1097 elf32_i860_is_local_label_name (abfd
, name
)
1101 if (name
[0] == '.' && name
[1] == 'e' && name
[2] == 'p' && name
[3] == '.')
1104 return _bfd_elf_is_local_label_name (abfd
, name
);
1109 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1110 #define TARGET_BIG_NAME "elf32-i860"
1111 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1112 #define TARGET_LITTLE_NAME "elf32-i860-little"
1113 #define ELF_ARCH bfd_arch_i860
1114 #define ELF_MACHINE_CODE EM_860
1115 #define ELF_MAXPAGESIZE 4096
1117 #define elf_info_to_howto_rel NULL
1118 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1119 #define elf_backend_relocate_section elf32_i860_relocate_section
1120 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1121 #define bfd_elf32_bfd_is_local_label_name elf32_i860_is_local_label_name
1123 #include "elf32-target.h"