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
);
718 value
+= rello
->r_addend
;
720 /* Separate the fields and insert. */
721 value
= (((value
& 0xf8) << 5) | (value
& 0x7ff)) & howto
->dst_mask
;
722 insn
= (insn
& ~howto
->dst_mask
) | value
;
724 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
729 /* Specialized relocation handler for R_860_PC16. This relocation
730 involves a 16-bit, PC-relative field that is split into two contiguous
732 static bfd_reloc_status_type
733 elf32_i860_relocate_pc16 (input_bfd
, input_section
, rello
, contents
, value
)
735 asection
*input_section
;
736 Elf_Internal_Rela
*rello
;
741 reloc_howto_type
*howto
;
742 howto
= lookup_howto (ELF32_R_TYPE (rello
->r_info
));
743 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
745 /* Adjust for PC-relative relocation. */
746 value
-= (input_section
->output_section
->vma
747 + input_section
->output_offset
);
748 value
-= rello
->r_offset
;
751 value
+= rello
->r_addend
;
753 /* Separate the fields and insert. */
754 value
= (((value
& 0xf8) << 5) | (value
& 0x7ff)) & howto
->dst_mask
;
755 insn
= (insn
& ~howto
->dst_mask
) | value
;
757 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
763 /* Specialized relocation handler for R_860_HIGHADJ. */
764 static bfd_reloc_status_type
765 elf32_i860_relocate_highadj (input_bfd
, rel
, contents
, value
)
767 Elf_Internal_Rela
*rel
;
773 insn
= bfd_get_32 (input_bfd
, contents
+ rel
->r_offset
);
775 value
+= ((rel
->r_addend
& 0x8000) << 1);
776 value
+= rel
->r_addend
;
777 value
= ((value
>> 16) & 0xffff);
779 insn
= (insn
& 0xffff0000) | value
;
781 bfd_put_32 (input_bfd
, insn
, contents
+ rel
->r_offset
);
786 /* Perform a single relocation. By default we use the standard BFD
787 routines. However, we handle some specially. */
788 static bfd_reloc_status_type
789 i860_final_link_relocate (howto
, input_bfd
, input_section
, contents
, rel
, relocation
)
790 reloc_howto_type
* howto
;
792 asection
* input_section
;
794 Elf_Internal_Rela
* rel
;
797 return _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
798 contents
, rel
->r_offset
, relocation
,
803 /* Relocate an i860 ELF section.
805 This is boiler-plate code copied from fr30.
806 There is some attempt to make this function usable for many architectures,
807 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
808 if only to serve as a learning tool.
810 The RELOCATE_SECTION function is called by the new ELF backend linker
811 to handle the relocations for a section.
813 The relocs are always passed as Rela structures; if the section
814 actually uses Rel structures, the r_addend field will always be
817 This function is responsible for adjusting the section contents as
818 necessary, and (if using Rela relocs and generating a relocateable
819 output file) adjusting the reloc addend as necessary.
821 This function does not have to worry about setting the reloc
822 address or the reloc symbol index.
824 LOCAL_SYMS is a pointer to the swapped in local symbols.
826 LOCAL_SECTIONS is an array giving the section in the input file
827 corresponding to the st_shndx field of each local symbol.
829 The global hash table entry for the global symbols can be found
830 via elf_sym_hashes (input_bfd).
832 When generating relocateable output, this function must handle
833 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
834 going to be the section symbol corresponding to the output
835 section, which means that the addend must be adjusted
838 elf32_i860_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
839 contents
, relocs
, local_syms
, local_sections
)
840 bfd
* output_bfd ATTRIBUTE_UNUSED
;
841 struct bfd_link_info
* info
;
843 asection
* input_section
;
845 Elf_Internal_Rela
* relocs
;
846 Elf_Internal_Sym
* local_syms
;
847 asection
** local_sections
;
849 Elf_Internal_Shdr
* symtab_hdr
;
850 struct elf_link_hash_entry
** sym_hashes
;
851 Elf_Internal_Rela
* rel
;
852 Elf_Internal_Rela
* relend
;
854 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
855 sym_hashes
= elf_sym_hashes (input_bfd
);
856 relend
= relocs
+ input_section
->reloc_count
;
858 for (rel
= relocs
; rel
< relend
; rel
++)
860 reloc_howto_type
* howto
;
861 unsigned long r_symndx
;
862 Elf_Internal_Sym
* sym
;
864 struct elf_link_hash_entry
* h
;
866 bfd_reloc_status_type r
;
867 const char * name
= NULL
;
870 r_type
= ELF32_R_TYPE (rel
->r_info
);
873 if ( r_type
== R_860_GNU_VTINHERIT
874 || r_type
== R_860_GNU_VTENTRY
)
878 r_symndx
= ELF32_R_SYM (rel
->r_info
);
880 if (info
->relocateable
)
882 /* This is a relocateable link. We don't have to change
883 anything, unless the reloc is against a section symbol,
884 in which case we have to adjust according to where the
885 section symbol winds up in the output section. */
886 if (r_symndx
< symtab_hdr
->sh_info
)
888 sym
= local_syms
+ r_symndx
;
890 if (ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
892 sec
= local_sections
[r_symndx
];
893 rel
->r_addend
+= sec
->output_offset
+ sym
->st_value
;
900 /* This is a final link. */
901 howto
= lookup_howto (ELF32_R_TYPE (rel
->r_info
));
906 if (r_symndx
< symtab_hdr
->sh_info
)
908 sym
= local_syms
+ r_symndx
;
909 sec
= local_sections
[r_symndx
];
910 relocation
= (sec
->output_section
->vma
914 name
= bfd_elf_string_from_elf_section
915 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
916 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
920 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
922 while (h
->root
.type
== bfd_link_hash_indirect
923 || h
->root
.type
== bfd_link_hash_warning
)
924 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
926 name
= h
->root
.root
.string
;
928 if (h
->root
.type
== bfd_link_hash_defined
929 || h
->root
.type
== bfd_link_hash_defweak
)
931 sec
= h
->root
.u
.def
.section
;
932 relocation
= (h
->root
.u
.def
.value
933 + sec
->output_section
->vma
934 + sec
->output_offset
);
936 else if (h
->root
.type
== bfd_link_hash_undefweak
)
942 if (! ((*info
->callbacks
->undefined_symbol
)
943 (info
, h
->root
.root
.string
, input_bfd
,
944 input_section
, rel
->r_offset
, true)))
953 r
= i860_final_link_relocate (howto
, input_bfd
, input_section
,
954 contents
, rel
, relocation
);
958 r
= elf32_i860_relocate_highadj (input_bfd
, rel
, contents
,
963 r
= elf32_i860_relocate_pc16 (input_bfd
, input_section
, rel
,
964 contents
, relocation
);
970 r
= elf32_i860_relocate_splitn (input_bfd
, rel
, contents
,
974 /* We do not yet handle GOT/PLT/Dynamic relocations. */
977 case R_860_JUMP_SLOT
:
984 case R_860_LOGOTOFF0
:
985 case R_860_SPGOTOFF0
:
986 case R_860_LOGOTOFF1
:
987 case R_860_SPGOTOFF1
:
988 case R_860_LOGOTOFF2
:
989 case R_860_LOGOTOFF3
:
996 r
= bfd_reloc_notsupported
;
1000 if (r
!= bfd_reloc_ok
)
1002 const char * msg
= (const char *) NULL
;
1006 case bfd_reloc_overflow
:
1007 r
= info
->callbacks
->reloc_overflow
1008 (info
, name
, howto
->name
, (bfd_vma
) 0,
1009 input_bfd
, input_section
, rel
->r_offset
);
1012 case bfd_reloc_undefined
:
1013 r
= info
->callbacks
->undefined_symbol
1014 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, true);
1017 case bfd_reloc_outofrange
:
1018 msg
= _("internal error: out of range error");
1021 case bfd_reloc_notsupported
:
1022 msg
= _("internal error: unsupported relocation error");
1025 case bfd_reloc_dangerous
:
1026 msg
= _("internal error: dangerous relocation");
1030 msg
= _("internal error: unknown error");
1035 r
= info
->callbacks
->warning
1036 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
1048 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1049 #define TARGET_BIG_NAME "elf32-i860"
1050 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1051 #define TARGET_LITTLE_NAME "elf32-i860-little"
1052 #define ELF_ARCH bfd_arch_i860
1053 #define ELF_MACHINE_CODE EM_860
1054 #define ELF_MAXPAGESIZE 4096
1056 #define elf_info_to_howto_rel NULL
1057 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1058 #define elf_backend_relocate_section elf32_i860_relocate_section
1059 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1061 #include "elf32-target.h"