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));
43 static bfd_reloc_status_type elf32_i860_relocate_pc16
44 PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
47 static bfd_reloc_status_type elf32_i860_relocate_highadj
48 PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
50 static boolean elf32_i860_relocate_section
51 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
52 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
54 static bfd_reloc_status_type i860_final_link_relocate
55 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
56 Elf_Internal_Rela *, bfd_vma));
60 /* This howto table is preliminary. */
61 static reloc_howto_type elf32_i860_howto_table [] =
63 /* This relocation does nothing. */
64 HOWTO (R_860_NONE, /* type */
66 2, /* size (0 = byte, 1 = short, 2 = long) */
68 false, /* pc_relative */
70 complain_overflow_bitfield, /* complain_on_overflow */
71 bfd_elf_generic_reloc, /* special_function */
72 "R_860_NONE", /* name */
73 false, /* partial_inplace */
76 false), /* pcrel_offset */
78 /* A 32-bit absolute relocation. */
79 HOWTO (R_860_32, /* type */
81 2, /* size (0 = byte, 1 = short, 2 = long) */
83 false, /* pc_relative */
85 complain_overflow_bitfield, /* complain_on_overflow */
86 bfd_elf_generic_reloc, /* special_function */
87 "R_860_32", /* name */
88 false, /* partial_inplace */
89 0xffffffff, /* src_mask */
90 0xffffffff, /* dst_mask */
91 false), /* pcrel_offset */
93 HOWTO (R_860_COPY, /* type */
95 2, /* size (0 = byte, 1 = short, 2 = long) */
97 false, /* pc_relative */
99 complain_overflow_bitfield, /* complain_on_overflow */
100 bfd_elf_generic_reloc, /* special_function */
101 "R_860_COPY", /* name */
102 true, /* partial_inplace */
103 0xffffffff, /* src_mask */
104 0xffffffff, /* dst_mask */
105 false), /* pcrel_offset */
107 HOWTO (R_860_GLOB_DAT, /* type */
109 2, /* size (0 = byte, 1 = short, 2 = long) */
111 false, /* pc_relative */
113 complain_overflow_bitfield, /* complain_on_overflow */
114 bfd_elf_generic_reloc, /* special_function */
115 "R_860_GLOB_DAT", /* name */
116 true, /* partial_inplace */
117 0xffffffff, /* src_mask */
118 0xffffffff, /* dst_mask */
119 false), /* pcrel_offset */
121 HOWTO (R_860_JUMP_SLOT, /* type */
123 2, /* size (0 = byte, 1 = short, 2 = long) */
125 false, /* pc_relative */
127 complain_overflow_bitfield, /* complain_on_overflow */
128 bfd_elf_generic_reloc, /* special_function */
129 "R_860_JUMP_SLOT", /* name */
130 true, /* partial_inplace */
131 0xffffffff, /* src_mask */
132 0xffffffff, /* dst_mask */
133 false), /* pcrel_offset */
135 HOWTO (R_860_RELATIVE, /* type */
137 2, /* size (0 = byte, 1 = short, 2 = long) */
139 false, /* pc_relative */
141 complain_overflow_bitfield, /* complain_on_overflow */
142 bfd_elf_generic_reloc, /* special_function */
143 "R_860_RELATIVE", /* name */
144 true, /* partial_inplace */
145 0xffffffff, /* src_mask */
146 0xffffffff, /* dst_mask */
147 false), /* pcrel_offset */
149 /* A 26-bit PC-relative relocation. */
150 HOWTO (R_860_PC26, /* type */
152 2, /* size (0 = byte, 1 = short, 2 = long) */
154 true, /* pc_relative */
156 complain_overflow_bitfield, /* complain_on_overflow */
157 bfd_elf_generic_reloc, /* special_function */
158 "R_860_PC26", /* name */
159 false, /* partial_inplace */
160 0x3ffffff, /* src_mask */
161 0x3ffffff, /* dst_mask */
162 true), /* pcrel_offset */
164 HOWTO (R_860_PLT26, /* type */
166 2, /* size (0 = byte, 1 = short, 2 = long) */
168 true, /* pc_relative */
170 complain_overflow_bitfield, /* complain_on_overflow */
171 bfd_elf_generic_reloc, /* special_function */
172 "R_860_PLT26", /* name */
173 true, /* partial_inplace */
174 0xffffffff, /* src_mask */
175 0xffffffff, /* dst_mask */
176 true), /* pcrel_offset */
178 /* A 16-bit PC-relative relocation. */
179 HOWTO (R_860_PC16, /* type */
181 2, /* size (0 = byte, 1 = short, 2 = long) */
183 true, /* pc_relative */
185 complain_overflow_bitfield, /* complain_on_overflow */
186 bfd_elf_generic_reloc, /* special_function */
187 "R_860_PC16", /* name */
188 false, /* partial_inplace */
189 0x1f07ff, /* src_mask */
190 0x1f07ff, /* dst_mask */
191 true), /* pcrel_offset */
193 HOWTO (R_860_LOW0, /* type */
195 2, /* size (0 = byte, 1 = short, 2 = long) */
197 false, /* pc_relative */
199 complain_overflow_dont, /* complain_on_overflow */
200 bfd_elf_generic_reloc, /* special_function */
201 "R_860_LOW0", /* name */
202 false, /* partial_inplace */
203 0xffff, /* src_mask */
204 0xffff, /* dst_mask */
205 false), /* pcrel_offset */
207 HOWTO (R_860_SPLIT0, /* type */
209 2, /* size (0 = byte, 1 = short, 2 = long) */
211 false, /* pc_relative */
213 complain_overflow_dont, /* complain_on_overflow */
214 bfd_elf_generic_reloc, /* special_function */
215 "R_860_SPLIT0", /* name */
216 false, /* partial_inplace */
217 0x1f07ff, /* src_mask */
218 0x1f07ff, /* dst_mask */
219 false), /* pcrel_offset */
221 HOWTO (R_860_LOW1, /* type */
223 2, /* size (0 = byte, 1 = short, 2 = long) */
225 false, /* pc_relative */
227 complain_overflow_dont, /* complain_on_overflow */
228 bfd_elf_generic_reloc, /* special_function */
229 "R_860_LOW1", /* name */
230 false, /* partial_inplace */
231 0xfffe, /* src_mask */
232 0xfffe, /* dst_mask */
233 false), /* pcrel_offset */
235 HOWTO (R_860_SPLIT1, /* type */
237 2, /* size (0 = byte, 1 = short, 2 = long) */
239 false, /* pc_relative */
241 complain_overflow_dont, /* complain_on_overflow */
242 bfd_elf_generic_reloc, /* special_function */
243 "R_860_SPLIT1", /* name */
244 false, /* partial_inplace */
245 0x1f07fe, /* src_mask */
246 0x1f07fe, /* dst_mask */
247 false), /* pcrel_offset */
249 HOWTO (R_860_LOW2, /* type */
251 2, /* size (0 = byte, 1 = short, 2 = long) */
253 false, /* pc_relative */
255 complain_overflow_dont, /* complain_on_overflow */
256 bfd_elf_generic_reloc, /* special_function */
257 "R_860_LOW2", /* name */
258 false, /* partial_inplace */
259 0xfffc, /* src_mask */
260 0xfffc, /* dst_mask */
261 false), /* pcrel_offset */
263 HOWTO (R_860_SPLIT2, /* type */
265 2, /* size (0 = byte, 1 = short, 2 = long) */
267 false, /* pc_relative */
269 complain_overflow_dont, /* complain_on_overflow */
270 bfd_elf_generic_reloc, /* special_function */
271 "R_860_SPLIT2", /* name */
272 false, /* partial_inplace */
273 0x1f07fc, /* src_mask */
274 0x1f07fc, /* dst_mask */
275 false), /* pcrel_offset */
277 HOWTO (R_860_LOW3, /* type */
279 2, /* size (0 = byte, 1 = short, 2 = long) */
281 false, /* pc_relative */
283 complain_overflow_dont, /* complain_on_overflow */
284 bfd_elf_generic_reloc, /* special_function */
285 "R_860_LOW3", /* name */
286 false, /* partial_inplace */
287 0xfff8, /* src_mask */
288 0xfff8, /* dst_mask */
289 false), /* pcrel_offset */
291 HOWTO (R_860_LOGOT0, /* type */
293 2, /* size (0 = byte, 1 = short, 2 = long) */
295 false, /* pc_relative */
297 complain_overflow_dont, /* complain_on_overflow */
298 bfd_elf_generic_reloc, /* special_function */
299 "R_860_LOGOT0", /* name */
300 false, /* partial_inplace */
302 0xffff, /* dst_mask */
303 true), /* pcrel_offset */
305 HOWTO (R_860_SPGOT0, /* type */
307 2, /* size (0 = byte, 1 = short, 2 = long) */
309 false, /* pc_relative */
311 complain_overflow_dont, /* complain_on_overflow */
312 bfd_elf_generic_reloc, /* special_function */
313 "R_860_SPGOT0", /* name */
314 false, /* partial_inplace */
316 0xffff, /* dst_mask */
317 true), /* pcrel_offset */
319 HOWTO (R_860_LOGOT1, /* type */
321 2, /* size (0 = byte, 1 = short, 2 = long) */
323 false, /* pc_relative */
325 complain_overflow_dont, /* complain_on_overflow */
326 bfd_elf_generic_reloc, /* special_function */
327 "R_860_LOGOT1", /* name */
328 false, /* partial_inplace */
330 0xffff, /* dst_mask */
331 true), /* pcrel_offset */
333 HOWTO (R_860_SPGOT1, /* type */
335 2, /* size (0 = byte, 1 = short, 2 = long) */
337 false, /* pc_relative */
339 complain_overflow_dont, /* complain_on_overflow */
340 bfd_elf_generic_reloc, /* special_function */
341 "R_860_SPGOT1", /* name */
342 false, /* partial_inplace */
344 0xffff, /* dst_mask */
345 true), /* pcrel_offset */
347 HOWTO (R_860_LOGOTOFF0, /* type */
349 2, /* size (0 = byte, 1 = short, 2 = long) */
351 false, /* pc_relative */
353 complain_overflow_dont, /* complain_on_overflow */
354 bfd_elf_generic_reloc, /* special_function */
355 "R_860_LOGOTOFF0", /* name */
356 true, /* partial_inplace */
357 0xffffffff, /* src_mask */
358 0xffffffff, /* dst_mask */
359 false), /* pcrel_offset */
361 HOWTO (R_860_SPGOTOFF0, /* type */
363 2, /* size (0 = byte, 1 = short, 2 = long) */
365 false, /* pc_relative */
367 complain_overflow_dont, /* complain_on_overflow */
368 bfd_elf_generic_reloc, /* special_function */
369 "R_860_SPGOTOFF0", /* name */
370 true, /* partial_inplace */
371 0xffffffff, /* src_mask */
372 0xffffffff, /* dst_mask */
373 false), /* pcrel_offset */
375 HOWTO (R_860_LOGOTOFF1, /* type */
377 2, /* size (0 = byte, 1 = short, 2 = long) */
379 false, /* pc_relative */
381 complain_overflow_dont, /* complain_on_overflow */
382 bfd_elf_generic_reloc, /* special_function */
383 "R_860_LOGOTOFF1", /* name */
384 true, /* partial_inplace */
385 0xffffffff, /* src_mask */
386 0xffffffff, /* dst_mask */
387 false), /* pcrel_offset */
389 HOWTO (R_860_SPGOTOFF1, /* type */
391 2, /* size (0 = byte, 1 = short, 2 = long) */
393 false, /* pc_relative */
395 complain_overflow_dont, /* complain_on_overflow */
396 bfd_elf_generic_reloc, /* special_function */
397 "R_860_SPGOTOFF1", /* name */
398 true, /* partial_inplace */
399 0xffffffff, /* src_mask */
400 0xffffffff, /* dst_mask */
401 false), /* pcrel_offset */
403 HOWTO (R_860_LOGOTOFF2, /* type */
405 2, /* size (0 = byte, 1 = short, 2 = long) */
407 false, /* pc_relative */
409 complain_overflow_dont, /* complain_on_overflow */
410 bfd_elf_generic_reloc, /* special_function */
411 "R_860_LOGOTOFF2", /* name */
412 true, /* partial_inplace */
413 0xffffffff, /* src_mask */
414 0xffffffff, /* dst_mask */
415 false), /* pcrel_offset */
417 HOWTO (R_860_LOGOTOFF3, /* type */
419 2, /* size (0 = byte, 1 = short, 2 = long) */
421 false, /* pc_relative */
423 complain_overflow_dont, /* complain_on_overflow */
424 bfd_elf_generic_reloc, /* special_function */
425 "R_860_LOGOTOFF3", /* name */
426 true, /* partial_inplace */
427 0xffffffff, /* src_mask */
428 0xffffffff, /* dst_mask */
429 false), /* pcrel_offset */
431 HOWTO (R_860_LOPC, /* type */
433 2, /* size (0 = byte, 1 = short, 2 = long) */
435 true, /* pc_relative */
437 complain_overflow_bitfield, /* complain_on_overflow */
438 bfd_elf_generic_reloc, /* special_function */
439 "R_860_LOPC", /* name */
440 false, /* partial_inplace */
441 0xffff, /* src_mask */
442 0xffff, /* dst_mask */
443 true), /* pcrel_offset */
445 HOWTO (R_860_HIGHADJ, /* type */
447 2, /* size (0 = byte, 1 = short, 2 = long) */
449 false, /* pc_relative */
451 complain_overflow_dont, /* complain_on_overflow */
452 bfd_elf_generic_reloc, /* special_function */
453 "R_860_HIGHADJ", /* name */
454 false, /* partial_inplace */
455 0xffff, /* src_mask */
456 0xffff, /* dst_mask */
457 false), /* pcrel_offset */
459 HOWTO (R_860_HAGOT, /* type */
461 2, /* size (0 = byte, 1 = short, 2 = long) */
463 false, /* pc_relative */
465 complain_overflow_dont, /* complain_on_overflow */
466 bfd_elf_generic_reloc, /* special_function */
467 "R_860_HAGOT", /* name */
468 false, /* partial_inplace */
470 0xffff, /* dst_mask */
471 true), /* pcrel_offset */
473 HOWTO (R_860_HAGOTOFF, /* type */
475 2, /* size (0 = byte, 1 = short, 2 = long) */
477 false, /* pc_relative */
479 complain_overflow_dont, /* complain_on_overflow */
480 bfd_elf_generic_reloc, /* special_function */
481 "R_860_HAGOTOFF", /* name */
482 true, /* partial_inplace */
483 0xffffffff, /* src_mask */
484 0xffffffff, /* dst_mask */
485 false), /* pcrel_offset */
487 HOWTO (R_860_HAPC, /* type */
489 2, /* size (0 = byte, 1 = short, 2 = long) */
491 true, /* pc_relative */
493 complain_overflow_bitfield, /* complain_on_overflow */
494 bfd_elf_generic_reloc, /* special_function */
495 "R_860_HAPC", /* name */
496 false, /* partial_inplace */
497 0xffff, /* src_mask */
498 0xffff, /* dst_mask */
499 true), /* pcrel_offset */
501 HOWTO (R_860_HIGH, /* type */
503 2, /* size (0 = byte, 1 = short, 2 = long) */
505 false, /* pc_relative */
507 complain_overflow_dont, /* complain_on_overflow */
508 bfd_elf_generic_reloc, /* special_function */
509 "R_860_HIGH", /* name */
510 false, /* partial_inplace */
511 0xffff, /* src_mask */
512 0xffff, /* dst_mask */
513 false), /* pcrel_offset */
515 HOWTO (R_860_HIGOT, /* type */
517 2, /* size (0 = byte, 1 = short, 2 = long) */
519 false, /* pc_relative */
521 complain_overflow_dont, /* complain_on_overflow */
522 bfd_elf_generic_reloc, /* special_function */
523 "R_860_HIGOT", /* name */
524 false, /* partial_inplace */
526 0xffff, /* dst_mask */
527 true), /* pcrel_offset */
529 HOWTO (R_860_HIGOTOFF, /* type */
531 2, /* size (0 = byte, 1 = short, 2 = long) */
533 false, /* pc_relative */
535 complain_overflow_dont, /* complain_on_overflow */
536 bfd_elf_generic_reloc, /* special_function */
537 "R_860_HIGOTOFF", /* name */
538 true, /* partial_inplace */
539 0xffffffff, /* src_mask */
540 0xffffffff, /* dst_mask */
541 false), /* pcrel_offset */
545 static unsigned char elf_code_to_howto_index[R_860_max + 1];
547 static reloc_howto_type *
551 static int initialized = 0;
553 int howto_tbl_size = (int) (sizeof (elf32_i860_howto_table)
554 / sizeof (elf32_i860_howto_table[0]));
559 memset (elf_code_to_howto_index, 0xff,
560 sizeof (elf_code_to_howto_index));
561 for (i = 0; i < howto_tbl_size; i++)
562 elf_code_to_howto_index[elf32_i860_howto_table[i].type] = i;
565 BFD_ASSERT (rtype <= R_860_max);
566 i = elf_code_to_howto_index[rtype];
567 if (i >= howto_tbl_size)
569 return elf32_i860_howto_table + i;
573 /* Given a BFD reloc, return the matching HOWTO structure. */
574 static reloc_howto_type *
575 elf32_i860_reloc_type_lookup (abfd, code)
576 bfd * abfd ATTRIBUTE_UNUSED;
577 bfd_reloc_code_real_type code;
589 case BFD_RELOC_860_COPY:
592 case BFD_RELOC_860_GLOB_DAT:
593 rtype = R_860_GLOB_DAT;
595 case BFD_RELOC_860_JUMP_SLOT:
596 rtype = R_860_JUMP_SLOT;
598 case BFD_RELOC_860_RELATIVE:
599 rtype = R_860_RELATIVE;
601 case BFD_RELOC_860_PC26:
604 case BFD_RELOC_860_PLT26:
607 case BFD_RELOC_860_PC16:
610 case BFD_RELOC_860_LOW0:
613 case BFD_RELOC_860_SPLIT0:
614 rtype = R_860_SPLIT0;
616 case BFD_RELOC_860_LOW1:
619 case BFD_RELOC_860_SPLIT1:
620 rtype = R_860_SPLIT1;
622 case BFD_RELOC_860_LOW2:
625 case BFD_RELOC_860_SPLIT2:
626 rtype = R_860_SPLIT2;
628 case BFD_RELOC_860_LOW3:
631 case BFD_RELOC_860_LOGOT0:
632 rtype = R_860_LOGOT0;
634 case BFD_RELOC_860_SPGOT0:
635 rtype = R_860_SPGOT0;
637 case BFD_RELOC_860_LOGOT1:
638 rtype = R_860_LOGOT1;
640 case BFD_RELOC_860_SPGOT1:
641 rtype = R_860_SPGOT1;
643 case BFD_RELOC_860_LOGOTOFF0:
644 rtype = R_860_LOGOTOFF0;
646 case BFD_RELOC_860_SPGOTOFF0:
647 rtype = R_860_SPGOTOFF0;
649 case BFD_RELOC_860_LOGOTOFF1:
650 rtype = R_860_LOGOTOFF1;
652 case BFD_RELOC_860_SPGOTOFF1:
653 rtype = R_860_SPGOTOFF1;
655 case BFD_RELOC_860_LOGOTOFF2:
656 rtype = R_860_LOGOTOFF2;
658 case BFD_RELOC_860_LOGOTOFF3:
659 rtype = R_860_LOGOTOFF3;
661 case BFD_RELOC_860_LOPC:
664 case BFD_RELOC_860_HIGHADJ:
665 rtype = R_860_HIGHADJ;
667 case BFD_RELOC_860_HAGOT:
670 case BFD_RELOC_860_HAGOTOFF:
671 rtype = R_860_HAGOTOFF;
673 case BFD_RELOC_860_HAPC:
676 case BFD_RELOC_860_HIGH:
679 case BFD_RELOC_860_HIGOT:
682 case BFD_RELOC_860_HIGOTOFF:
683 rtype = R_860_HIGOTOFF;
689 return lookup_howto (rtype);
693 /* Given a ELF reloc, return the matching HOWTO structure. */
695 elf32_i860_info_to_howto_rela (abfd, bfd_reloc, elf_reloc)
696 bfd *abfd ATTRIBUTE_UNUSED;
698 Elf64_Internal_Rela *elf_reloc;
700 bfd_reloc->howto = lookup_howto (ELF32_R_TYPE (elf_reloc->r_info));
705 /* Specialized relocation handler for R_860_SPLITn. These relocations
706 involves a 16-bit field that is split into two contiguous parts. */
707 static bfd_reloc_status_type
708 elf32_i860_relocate_splitn (input_bfd, rello, contents, value)
710 Elf_Internal_Rela *rello;
715 reloc_howto_type *howto;
716 howto = lookup_howto (ELF32_R_TYPE (rello->r_info));
717 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
719 /* Remove encode bits and intervening bits. Then concatenate the
720 two fields into one 16-bit quantity. */
721 t = (insn & howto->src_mask);
722 t = ((t >> 5) & 0xf8) | (t & 0x7ff);
725 value += (rello->r_addend + t);
727 /* Separate the fields and re-insert. */
728 value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
729 insn = (insn & ~howto->dst_mask) | value;
731 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
737 /* Specialized relocation handler for R_860_PC16. This relocation
738 involves a 16-bit, PC-relative field that is split into two contiguous
740 static bfd_reloc_status_type
741 elf32_i860_relocate_pc16 (input_bfd, rello, contents, value)
743 Elf_Internal_Rela *rello;
751 /* Specialized relocation handler for R_860_HIGHADJ. */
752 static bfd_reloc_status_type
753 elf32_i860_relocate_highadj (input_bfd, rel, contents, value)
755 Elf_Internal_Rela *rel;
761 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
763 value += ((rel->r_addend & 0x8000) << 1);
764 value += rel->r_addend;
765 value = ((value >> 16) & 0xffff);
766 value = (value + (insn & 0xffff)) & 0xffff;
768 insn = (insn & 0xffff0000) | value;
770 bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
775 /* Perform a single relocation. By default we use the standard BFD
776 routines. However, we handle some specially. */
777 static bfd_reloc_status_type
778 i860_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation)
779 reloc_howto_type * howto;
781 asection * input_section;
783 Elf_Internal_Rela * rel;
786 return _bfd_final_link_relocate (howto, input_bfd, input_section,
787 contents, rel->r_offset, relocation,
792 /* Relocate an i860 ELF section.
794 This is boiler-plate code copied from fr30.
795 There is some attempt to make this function usable for many architectures,
796 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
797 if only to serve as a learning tool.
799 The RELOCATE_SECTION function is called by the new ELF backend linker
800 to handle the relocations for a section.
802 The relocs are always passed as Rela structures; if the section
803 actually uses Rel structures, the r_addend field will always be
806 This function is responsible for adjusting the section contents as
807 necessary, and (if using Rela relocs and generating a relocateable
808 output file) adjusting the reloc addend as necessary.
810 This function does not have to worry about setting the reloc
811 address or the reloc symbol index.
813 LOCAL_SYMS is a pointer to the swapped in local symbols.
815 LOCAL_SECTIONS is an array giving the section in the input file
816 corresponding to the st_shndx field of each local symbol.
818 The global hash table entry for the global symbols can be found
819 via elf_sym_hashes (input_bfd).
821 When generating relocateable output, this function must handle
822 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
823 going to be the section symbol corresponding to the output
824 section, which means that the addend must be adjusted
827 elf32_i860_relocate_section (output_bfd, info, input_bfd, input_section,
828 contents, relocs, local_syms, local_sections)
829 bfd * output_bfd ATTRIBUTE_UNUSED;
830 struct bfd_link_info * info;
832 asection * input_section;
834 Elf_Internal_Rela * relocs;
835 Elf_Internal_Sym * local_syms;
836 asection ** local_sections;
838 Elf_Internal_Shdr * symtab_hdr;
839 struct elf_link_hash_entry ** sym_hashes;
840 Elf_Internal_Rela * rel;
841 Elf_Internal_Rela * relend;
843 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
844 sym_hashes = elf_sym_hashes (input_bfd);
845 relend = relocs + input_section->reloc_count;
847 for (rel = relocs; rel < relend; rel ++)
849 reloc_howto_type * howto;
850 unsigned long r_symndx;
851 Elf_Internal_Sym * sym;
853 struct elf_link_hash_entry * h;
855 bfd_reloc_status_type r;
856 const char * name = NULL;
859 r_type = ELF32_R_TYPE (rel->r_info);
862 if ( r_type == R_860_GNU_VTINHERIT
863 || r_type == R_860_GNU_VTENTRY)
867 r_symndx = ELF32_R_SYM (rel->r_info);
869 if (info->relocateable)
871 /* This is a relocateable link. We don't have to change
872 anything, unless the reloc is against a section symbol,
873 in which case we have to adjust according to where the
874 section symbol winds up in the output section. */
875 if (r_symndx < symtab_hdr->sh_info)
877 sym = local_syms + r_symndx;
879 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
881 sec = local_sections [r_symndx];
882 rel->r_addend += sec->output_offset + sym->st_value;
889 /* This is a final link. */
890 howto = lookup_howto (ELF32_R_TYPE (rel->r_info));
895 if (r_symndx < symtab_hdr->sh_info)
897 sym = local_syms + r_symndx;
898 sec = local_sections [r_symndx];
899 relocation = (sec->output_section->vma
903 name = bfd_elf_string_from_elf_section
904 (input_bfd, symtab_hdr->sh_link, sym->st_name);
905 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
909 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
911 while (h->root.type == bfd_link_hash_indirect
912 || h->root.type == bfd_link_hash_warning)
913 h = (struct elf_link_hash_entry *) h->root.u.i.link;
915 name = h->root.root.string;
917 if (h->root.type == bfd_link_hash_defined
918 || h->root.type == bfd_link_hash_defweak)
920 sec = h->root.u.def.section;
921 relocation = (h->root.u.def.value
922 + sec->output_section->vma
923 + sec->output_offset);
925 else if (h->root.type == bfd_link_hash_undefweak)
931 if (! ((*info->callbacks->undefined_symbol)
932 (info, h->root.root.string, input_bfd,
933 input_section, rel->r_offset, true)))
942 r = i860_final_link_relocate (howto, input_bfd, input_section,
943 contents, rel, relocation);
947 r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
953 r = elf32_i860_relocate_pc16 (input_bfd, rel, contents,
961 r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
965 /* We do not yet handle GOT/PLT/Dynamic relocations. */
968 case R_860_JUMP_SLOT:
975 case R_860_LOGOTOFF0:
976 case R_860_SPGOTOFF0:
977 case R_860_LOGOTOFF1:
978 case R_860_SPGOTOFF1:
979 case R_860_LOGOTOFF2:
980 case R_860_LOGOTOFF3:
987 r = bfd_reloc_notsupported;
991 if (r != bfd_reloc_ok)
993 const char * msg = (const char *) NULL;
997 case bfd_reloc_overflow:
998 r = info->callbacks->reloc_overflow
999 (info, name, howto->name, (bfd_vma) 0,
1000 input_bfd, input_section, rel->r_offset);
1003 case bfd_reloc_undefined:
1004 r = info->callbacks->undefined_symbol
1005 (info, name, input_bfd, input_section, rel->r_offset, true);
1008 case bfd_reloc_outofrange:
1009 msg = _("internal error: out of range error");
1012 case bfd_reloc_notsupported:
1013 msg = _("internal error: unsupported relocation error");
1016 case bfd_reloc_dangerous:
1017 msg = _("internal error: dangerous relocation");
1021 msg = _("internal error: unknown error");
1026 r = info->callbacks->warning
1027 (info, msg, name, input_bfd, input_section, rel->r_offset);
1039 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1040 #define TARGET_BIG_NAME "elf32-i860"
1041 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1042 #define TARGET_LITTLE_NAME "elf32-i860-little"
1043 #define ELF_ARCH bfd_arch_i860
1044 #define ELF_MACHINE_CODE EM_860
1045 #define ELF_MAXPAGESIZE 4096
1047 #define elf_info_to_howto_rel NULL
1048 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1049 #define elf_backend_relocate_section elf32_i860_relocate_section
1050 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1052 #include "elf32-target.h"