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_highadj
46 PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
48 static boolean elf32_i860_relocate_section
49 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
50 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
52 static bfd_reloc_status_type i860_final_link_relocate
53 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
54 Elf_Internal_Rela *, bfd_vma));
58 /* This howto table is preliminary. */
59 static reloc_howto_type elf32_i860_howto_table [] =
61 /* This relocation does nothing. */
62 HOWTO (R_860_NONE, /* type */
64 2, /* size (0 = byte, 1 = short, 2 = long) */
66 false, /* pc_relative */
68 complain_overflow_bitfield, /* complain_on_overflow */
69 bfd_elf_generic_reloc, /* special_function */
70 "R_860_NONE", /* name */
71 false, /* partial_inplace */
74 false), /* pcrel_offset */
76 /* A 32-bit absolute relocation. */
77 HOWTO (R_860_32, /* 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_32", /* name */
86 false, /* partial_inplace */
87 0xffffffff, /* src_mask */
88 0xffffffff, /* dst_mask */
89 false), /* pcrel_offset */
91 HOWTO (R_860_COPY, /* 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_COPY", /* name */
100 true, /* partial_inplace */
101 0xffffffff, /* src_mask */
102 0xffffffff, /* dst_mask */
103 false), /* pcrel_offset */
105 HOWTO (R_860_GLOB_DAT, /* 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_GLOB_DAT", /* name */
114 true, /* partial_inplace */
115 0xffffffff, /* src_mask */
116 0xffffffff, /* dst_mask */
117 false), /* pcrel_offset */
119 HOWTO (R_860_JUMP_SLOT, /* type */
121 2, /* size (0 = byte, 1 = short, 2 = long) */
123 false, /* pc_relative */
125 complain_overflow_bitfield, /* complain_on_overflow */
126 bfd_elf_generic_reloc, /* special_function */
127 "R_860_JUMP_SLOT", /* name */
128 true, /* partial_inplace */
129 0xffffffff, /* src_mask */
130 0xffffffff, /* dst_mask */
131 false), /* pcrel_offset */
133 HOWTO (R_860_RELATIVE, /* type */
135 2, /* size (0 = byte, 1 = short, 2 = long) */
137 false, /* pc_relative */
139 complain_overflow_bitfield, /* complain_on_overflow */
140 bfd_elf_generic_reloc, /* special_function */
141 "R_860_RELATIVE", /* name */
142 true, /* partial_inplace */
143 0xffffffff, /* src_mask */
144 0xffffffff, /* dst_mask */
145 false), /* pcrel_offset */
147 /* A 26-bit PC-relative relocation. */
148 HOWTO (R_860_PC26, /* type */
150 2, /* size (0 = byte, 1 = short, 2 = long) */
152 true, /* pc_relative */
154 complain_overflow_bitfield, /* complain_on_overflow */
155 bfd_elf_generic_reloc, /* special_function */
156 "R_860_PC26", /* name */
157 false, /* partial_inplace */
158 0x3ffffff, /* src_mask */
159 0x3ffffff, /* dst_mask */
160 true), /* pcrel_offset */
162 HOWTO (R_860_PLT26, /* type */
164 2, /* size (0 = byte, 1 = short, 2 = long) */
166 true, /* pc_relative */
168 complain_overflow_bitfield, /* complain_on_overflow */
169 bfd_elf_generic_reloc, /* special_function */
170 "R_860_PLT26", /* name */
171 true, /* partial_inplace */
172 0xffffffff, /* src_mask */
173 0xffffffff, /* dst_mask */
174 true), /* pcrel_offset */
176 /* A 16-bit PC-relative relocation. */
177 HOWTO (R_860_PC16, /* type */
179 2, /* size (0 = byte, 1 = short, 2 = long) */
181 true, /* pc_relative */
183 complain_overflow_bitfield, /* complain_on_overflow */
184 bfd_elf_generic_reloc, /* special_function */
185 "R_860_PC16", /* name */
186 false, /* partial_inplace */
187 0x1f07ff, /* src_mask */
188 0x1f07ff, /* dst_mask */
189 true), /* pcrel_offset */
191 HOWTO (R_860_LOW0, /* 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_LOW0", /* name */
200 false, /* partial_inplace */
201 0xffff, /* src_mask */
202 0xffff, /* dst_mask */
203 false), /* pcrel_offset */
205 HOWTO (R_860_SPLIT0, /* 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_SPLIT0", /* name */
214 false, /* partial_inplace */
215 0x1f07ff, /* src_mask */
216 0x1f07ff, /* dst_mask */
217 false), /* pcrel_offset */
219 HOWTO (R_860_LOW1, /* 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_LOW1", /* name */
228 false, /* partial_inplace */
229 0xfffe, /* src_mask */
230 0xfffe, /* dst_mask */
231 false), /* pcrel_offset */
233 HOWTO (R_860_SPLIT1, /* 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_SPLIT1", /* name */
242 false, /* partial_inplace */
243 0x1f07fe, /* src_mask */
244 0x1f07fe, /* dst_mask */
245 false), /* pcrel_offset */
247 HOWTO (R_860_LOW2, /* 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_LOW2", /* name */
256 false, /* partial_inplace */
257 0xfffc, /* src_mask */
258 0xfffc, /* dst_mask */
259 false), /* pcrel_offset */
261 HOWTO (R_860_SPLIT2, /* 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_SPLIT2", /* name */
270 false, /* partial_inplace */
271 0x1f07fc, /* src_mask */
272 0x1f07fc, /* dst_mask */
273 false), /* pcrel_offset */
275 HOWTO (R_860_LOW3, /* 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_LOW3", /* name */
284 false, /* partial_inplace */
285 0xfff8, /* src_mask */
286 0xfff8, /* dst_mask */
287 false), /* pcrel_offset */
289 HOWTO (R_860_LOGOT0, /* 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_LOGOT0", /* name */
298 false, /* partial_inplace */
300 0xffff, /* dst_mask */
301 true), /* pcrel_offset */
303 HOWTO (R_860_SPGOT0, /* 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_SPGOT0", /* name */
312 false, /* partial_inplace */
314 0xffff, /* dst_mask */
315 true), /* pcrel_offset */
317 HOWTO (R_860_LOGOT1, /* 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_LOGOT1", /* name */
326 false, /* partial_inplace */
328 0xffff, /* dst_mask */
329 true), /* pcrel_offset */
331 HOWTO (R_860_SPGOT1, /* 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_SPGOT1", /* name */
340 false, /* partial_inplace */
342 0xffff, /* dst_mask */
343 true), /* pcrel_offset */
345 HOWTO (R_860_LOGOTOFF0, /* 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_LOGOTOFF0", /* name */
354 true, /* partial_inplace */
355 0xffffffff, /* src_mask */
356 0xffffffff, /* dst_mask */
357 false), /* pcrel_offset */
359 HOWTO (R_860_SPGOTOFF0, /* 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_SPGOTOFF0", /* name */
368 true, /* partial_inplace */
369 0xffffffff, /* src_mask */
370 0xffffffff, /* dst_mask */
371 false), /* pcrel_offset */
373 HOWTO (R_860_LOGOTOFF1, /* 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_LOGOTOFF1", /* name */
382 true, /* partial_inplace */
383 0xffffffff, /* src_mask */
384 0xffffffff, /* dst_mask */
385 false), /* pcrel_offset */
387 HOWTO (R_860_SPGOTOFF1, /* 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_SPGOTOFF1", /* name */
396 true, /* partial_inplace */
397 0xffffffff, /* src_mask */
398 0xffffffff, /* dst_mask */
399 false), /* pcrel_offset */
401 HOWTO (R_860_LOGOTOFF2, /* type */
403 2, /* size (0 = byte, 1 = short, 2 = long) */
405 false, /* pc_relative */
407 complain_overflow_dont, /* complain_on_overflow */
408 bfd_elf_generic_reloc, /* special_function */
409 "R_860_LOGOTOFF2", /* name */
410 true, /* partial_inplace */
411 0xffffffff, /* src_mask */
412 0xffffffff, /* dst_mask */
413 false), /* pcrel_offset */
415 HOWTO (R_860_LOGOTOFF3, /* 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_LOGOTOFF3", /* name */
424 true, /* partial_inplace */
425 0xffffffff, /* src_mask */
426 0xffffffff, /* dst_mask */
427 false), /* pcrel_offset */
429 HOWTO (R_860_LOPC, /* type */
431 2, /* size (0 = byte, 1 = short, 2 = long) */
433 true, /* pc_relative */
435 complain_overflow_bitfield, /* complain_on_overflow */
436 bfd_elf_generic_reloc, /* special_function */
437 "R_860_LOPC", /* name */
438 false, /* partial_inplace */
439 0xffff, /* src_mask */
440 0xffff, /* dst_mask */
441 true), /* pcrel_offset */
443 HOWTO (R_860_HIGHADJ, /* 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_HIGHADJ", /* name */
452 false, /* partial_inplace */
453 0xffff, /* src_mask */
454 0xffff, /* dst_mask */
455 false), /* pcrel_offset */
457 HOWTO (R_860_HAGOT, /* type */
459 2, /* size (0 = byte, 1 = short, 2 = long) */
461 false, /* pc_relative */
463 complain_overflow_dont, /* complain_on_overflow */
464 bfd_elf_generic_reloc, /* special_function */
465 "R_860_HAGOT", /* name */
466 false, /* partial_inplace */
468 0xffff, /* dst_mask */
469 true), /* pcrel_offset */
471 HOWTO (R_860_HAGOTOFF, /* 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_HAGOTOFF", /* name */
480 true, /* partial_inplace */
481 0xffffffff, /* src_mask */
482 0xffffffff, /* dst_mask */
483 false), /* pcrel_offset */
485 HOWTO (R_860_HAPC, /* type */
487 2, /* size (0 = byte, 1 = short, 2 = long) */
489 true, /* pc_relative */
491 complain_overflow_bitfield, /* complain_on_overflow */
492 bfd_elf_generic_reloc, /* special_function */
493 "R_860_HAPC", /* name */
494 false, /* partial_inplace */
495 0xffff, /* src_mask */
496 0xffff, /* dst_mask */
497 true), /* pcrel_offset */
499 HOWTO (R_860_HIGH, /* 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_HIGH", /* name */
508 false, /* partial_inplace */
509 0xffff, /* src_mask */
510 0xffff, /* dst_mask */
511 false), /* pcrel_offset */
513 HOWTO (R_860_HIGOT, /* type */
515 2, /* size (0 = byte, 1 = short, 2 = long) */
517 false, /* pc_relative */
519 complain_overflow_dont, /* complain_on_overflow */
520 bfd_elf_generic_reloc, /* special_function */
521 "R_860_HIGOT", /* name */
522 false, /* partial_inplace */
524 0xffff, /* dst_mask */
525 true), /* pcrel_offset */
527 HOWTO (R_860_HIGOTOFF, /* type */
529 2, /* size (0 = byte, 1 = short, 2 = long) */
531 false, /* pc_relative */
533 complain_overflow_dont, /* complain_on_overflow */
534 bfd_elf_generic_reloc, /* special_function */
535 "R_860_HIGOTOFF", /* name */
536 true, /* partial_inplace */
537 0xffffffff, /* src_mask */
538 0xffffffff, /* dst_mask */
539 false), /* pcrel_offset */
543 static unsigned char elf_code_to_howto_index[R_860_max + 1];
545 static reloc_howto_type *
549 static int initialized = 0;
551 int howto_tbl_size = (int) (sizeof (elf32_i860_howto_table)
552 / sizeof (elf32_i860_howto_table[0]));
557 memset (elf_code_to_howto_index, 0xff,
558 sizeof (elf_code_to_howto_index));
559 for (i = 0; i < howto_tbl_size; i++)
560 elf_code_to_howto_index[elf32_i860_howto_table[i].type] = i;
563 BFD_ASSERT (rtype <= R_860_max);
564 i = elf_code_to_howto_index[rtype];
565 if (i >= howto_tbl_size)
567 return elf32_i860_howto_table + i;
571 /* Given a BFD reloc, return the matching HOWTO structure. */
572 static reloc_howto_type *
573 elf32_i860_reloc_type_lookup (abfd, code)
574 bfd * abfd ATTRIBUTE_UNUSED;
575 bfd_reloc_code_real_type code;
587 case BFD_RELOC_860_COPY:
590 case BFD_RELOC_860_GLOB_DAT:
591 rtype = R_860_GLOB_DAT;
593 case BFD_RELOC_860_JUMP_SLOT:
594 rtype = R_860_JUMP_SLOT;
596 case BFD_RELOC_860_RELATIVE:
597 rtype = R_860_RELATIVE;
599 case BFD_RELOC_860_PC26:
602 case BFD_RELOC_860_PLT26:
605 case BFD_RELOC_860_PC16:
608 case BFD_RELOC_860_LOW0:
611 case BFD_RELOC_860_SPLIT0:
612 rtype = R_860_SPLIT0;
614 case BFD_RELOC_860_LOW1:
617 case BFD_RELOC_860_SPLIT1:
618 rtype = R_860_SPLIT1;
620 case BFD_RELOC_860_LOW2:
623 case BFD_RELOC_860_SPLIT2:
624 rtype = R_860_SPLIT2;
626 case BFD_RELOC_860_LOW3:
629 case BFD_RELOC_860_LOGOT0:
630 rtype = R_860_LOGOT0;
632 case BFD_RELOC_860_SPGOT0:
633 rtype = R_860_SPGOT0;
635 case BFD_RELOC_860_LOGOT1:
636 rtype = R_860_LOGOT1;
638 case BFD_RELOC_860_SPGOT1:
639 rtype = R_860_SPGOT1;
641 case BFD_RELOC_860_LOGOTOFF0:
642 rtype = R_860_LOGOTOFF0;
644 case BFD_RELOC_860_SPGOTOFF0:
645 rtype = R_860_SPGOTOFF0;
647 case BFD_RELOC_860_LOGOTOFF1:
648 rtype = R_860_LOGOTOFF1;
650 case BFD_RELOC_860_SPGOTOFF1:
651 rtype = R_860_SPGOTOFF1;
653 case BFD_RELOC_860_LOGOTOFF2:
654 rtype = R_860_LOGOTOFF2;
656 case BFD_RELOC_860_LOGOTOFF3:
657 rtype = R_860_LOGOTOFF3;
659 case BFD_RELOC_860_LOPC:
662 case BFD_RELOC_860_HIGHADJ:
663 rtype = R_860_HIGHADJ;
665 case BFD_RELOC_860_HAGOT:
668 case BFD_RELOC_860_HAGOTOFF:
669 rtype = R_860_HAGOTOFF;
671 case BFD_RELOC_860_HAPC:
674 case BFD_RELOC_860_HIGH:
677 case BFD_RELOC_860_HIGOT:
680 case BFD_RELOC_860_HIGOTOFF:
681 rtype = R_860_HIGOTOFF;
687 return lookup_howto (rtype);
691 /* Given a ELF reloc, return the matching HOWTO structure. */
693 elf32_i860_info_to_howto_rela (abfd, bfd_reloc, elf_reloc)
694 bfd *abfd ATTRIBUTE_UNUSED;
696 Elf64_Internal_Rela *elf_reloc;
698 bfd_reloc->howto = lookup_howto (ELF32_R_TYPE (elf_reloc->r_info));
703 /* Specialized relocation handler for R_860_SPLITn. These relocations
704 involves a 16-bit field that is split into two contiguous parts. */
705 static bfd_reloc_status_type
706 elf32_i860_relocate_splitn (input_bfd, rello, contents, value)
708 Elf_Internal_Rela *rello;
713 reloc_howto_type *howto;
714 howto = lookup_howto (ELF32_R_TYPE (rello->r_info));
715 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
717 /* Remove encode bits and intervening bits. Then concatenate the
718 two fields into one 16-bit quantity. */
719 t = (insn & howto->src_mask);
720 t = ((t >> 5) & 0xf8) | (t & 0x7ff);
723 value += (rello->r_addend + t);
725 /* Separate the fields and re-insert. */
726 value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
727 insn = (insn & ~howto->dst_mask) | value;
729 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
734 /* Specialized relocation handler for R_860_PC16. This relocation
735 involves a 16-bit, PC-relative field that is split into two contiguous
737 static bfd_reloc_status_type
738 elf32_i860_relocate_pc16 (input_bfd, input_section, rello, contents, value)
740 asection *input_section;
741 Elf_Internal_Rela *rello;
746 reloc_howto_type *howto;
747 howto = lookup_howto (ELF32_R_TYPE (rello->r_info));
748 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
750 /* Adjust for PC-relative relocation. */
751 value -= (input_section->output_section->vma
752 + input_section->output_offset);
753 value -= rello->r_offset;
755 /* Remove encode bits and intervening bits. Then concatenate the
756 two fields into one 16-bit quantity. */
757 t = (insn & howto->src_mask);
758 t = ((t >> 5) & 0xf8) | (t & 0x7ff);
761 value += (rello->r_addend + t);
763 /* Separate the fields and re-insert. */
764 value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
765 insn = (insn & ~howto->dst_mask) | value;
767 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
773 /* Specialized relocation handler for R_860_HIGHADJ. */
774 static bfd_reloc_status_type
775 elf32_i860_relocate_highadj (input_bfd, rel, contents, value)
777 Elf_Internal_Rela *rel;
783 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
785 value += ((rel->r_addend & 0x8000) << 1);
786 value += rel->r_addend;
787 value = ((value >> 16) & 0xffff);
788 value = (value + (insn & 0xffff)) & 0xffff;
790 insn = (insn & 0xffff0000) | value;
792 bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
797 /* Perform a single relocation. By default we use the standard BFD
798 routines. However, we handle some specially. */
799 static bfd_reloc_status_type
800 i860_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation)
801 reloc_howto_type * howto;
803 asection * input_section;
805 Elf_Internal_Rela * rel;
808 return _bfd_final_link_relocate (howto, input_bfd, input_section,
809 contents, rel->r_offset, relocation,
814 /* Relocate an i860 ELF section.
816 This is boiler-plate code copied from fr30.
817 There is some attempt to make this function usable for many architectures,
818 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
819 if only to serve as a learning tool.
821 The RELOCATE_SECTION function is called by the new ELF backend linker
822 to handle the relocations for a section.
824 The relocs are always passed as Rela structures; if the section
825 actually uses Rel structures, the r_addend field will always be
828 This function is responsible for adjusting the section contents as
829 necessary, and (if using Rela relocs and generating a relocateable
830 output file) adjusting the reloc addend as necessary.
832 This function does not have to worry about setting the reloc
833 address or the reloc symbol index.
835 LOCAL_SYMS is a pointer to the swapped in local symbols.
837 LOCAL_SECTIONS is an array giving the section in the input file
838 corresponding to the st_shndx field of each local symbol.
840 The global hash table entry for the global symbols can be found
841 via elf_sym_hashes (input_bfd).
843 When generating relocateable output, this function must handle
844 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
845 going to be the section symbol corresponding to the output
846 section, which means that the addend must be adjusted
849 elf32_i860_relocate_section (output_bfd, info, input_bfd, input_section,
850 contents, relocs, local_syms, local_sections)
851 bfd * output_bfd ATTRIBUTE_UNUSED;
852 struct bfd_link_info * info;
854 asection * input_section;
856 Elf_Internal_Rela * relocs;
857 Elf_Internal_Sym * local_syms;
858 asection ** local_sections;
860 Elf_Internal_Shdr * symtab_hdr;
861 struct elf_link_hash_entry ** sym_hashes;
862 Elf_Internal_Rela * rel;
863 Elf_Internal_Rela * relend;
865 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
866 sym_hashes = elf_sym_hashes (input_bfd);
867 relend = relocs + input_section->reloc_count;
869 for (rel = relocs; rel < relend; rel ++)
871 reloc_howto_type * howto;
872 unsigned long r_symndx;
873 Elf_Internal_Sym * sym;
875 struct elf_link_hash_entry * h;
877 bfd_reloc_status_type r;
878 const char * name = NULL;
881 r_type = ELF32_R_TYPE (rel->r_info);
884 if ( r_type == R_860_GNU_VTINHERIT
885 || r_type == R_860_GNU_VTENTRY)
889 r_symndx = ELF32_R_SYM (rel->r_info);
891 if (info->relocateable)
893 /* This is a relocateable link. We don't have to change
894 anything, unless the reloc is against a section symbol,
895 in which case we have to adjust according to where the
896 section symbol winds up in the output section. */
897 if (r_symndx < symtab_hdr->sh_info)
899 sym = local_syms + r_symndx;
901 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
903 sec = local_sections [r_symndx];
904 rel->r_addend += sec->output_offset + sym->st_value;
911 /* This is a final link. */
912 howto = lookup_howto (ELF32_R_TYPE (rel->r_info));
917 if (r_symndx < symtab_hdr->sh_info)
919 sym = local_syms + r_symndx;
920 sec = local_sections [r_symndx];
921 relocation = (sec->output_section->vma
925 name = bfd_elf_string_from_elf_section
926 (input_bfd, symtab_hdr->sh_link, sym->st_name);
927 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
931 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
933 while (h->root.type == bfd_link_hash_indirect
934 || h->root.type == bfd_link_hash_warning)
935 h = (struct elf_link_hash_entry *) h->root.u.i.link;
937 name = h->root.root.string;
939 if (h->root.type == bfd_link_hash_defined
940 || h->root.type == bfd_link_hash_defweak)
942 sec = h->root.u.def.section;
943 relocation = (h->root.u.def.value
944 + sec->output_section->vma
945 + sec->output_offset);
947 else if (h->root.type == bfd_link_hash_undefweak)
953 if (! ((*info->callbacks->undefined_symbol)
954 (info, h->root.root.string, input_bfd,
955 input_section, rel->r_offset, true)))
964 r = i860_final_link_relocate (howto, input_bfd, input_section,
965 contents, rel, relocation);
969 r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
974 r = elf32_i860_relocate_pc16 (input_bfd, input_section, rel,
975 contents, relocation);
981 r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
985 /* We do not yet handle GOT/PLT/Dynamic relocations. */
988 case R_860_JUMP_SLOT:
995 case R_860_LOGOTOFF0:
996 case R_860_SPGOTOFF0:
997 case R_860_LOGOTOFF1:
998 case R_860_SPGOTOFF1:
999 case R_860_LOGOTOFF2:
1000 case R_860_LOGOTOFF3:
1003 case R_860_HAGOTOFF:
1006 case R_860_HIGOTOFF:
1007 r = bfd_reloc_notsupported;
1011 if (r != bfd_reloc_ok)
1013 const char * msg = (const char *) NULL;
1017 case bfd_reloc_overflow:
1018 r = info->callbacks->reloc_overflow
1019 (info, name, howto->name, (bfd_vma) 0,
1020 input_bfd, input_section, rel->r_offset);
1023 case bfd_reloc_undefined:
1024 r = info->callbacks->undefined_symbol
1025 (info, name, input_bfd, input_section, rel->r_offset, true);
1028 case bfd_reloc_outofrange:
1029 msg = _("internal error: out of range error");
1032 case bfd_reloc_notsupported:
1033 msg = _("internal error: unsupported relocation error");
1036 case bfd_reloc_dangerous:
1037 msg = _("internal error: dangerous relocation");
1041 msg = _("internal error: unknown error");
1046 r = info->callbacks->warning
1047 (info, msg, name, input_bfd, input_section, rel->r_offset);
1059 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1060 #define TARGET_BIG_NAME "elf32-i860"
1061 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1062 #define TARGET_LITTLE_NAME "elf32-i860-little"
1063 #define ELF_ARCH bfd_arch_i860
1064 #define ELF_MACHINE_CODE EM_860
1065 #define ELF_MAXPAGESIZE 4096
1067 #define elf_info_to_howto_rel NULL
1068 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1069 #define elf_backend_relocate_section elf32_i860_relocate_section
1070 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1072 #include "elf32-target.h"