1 /* Intel i860 specific support for 32-bit ELF.
2 Copyright 1993, 1995, 1999, 2000, 2001 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. */
29 static reloc_howto_type
*lookup_howto
30 PARAMS ((unsigned int));
32 static reloc_howto_type
*elf32_i860_reloc_type_lookup
33 PARAMS ((bfd
*abfd
, bfd_reloc_code_real_type code
));
35 static void elf32_i860_info_to_howto_rela
36 PARAMS ((bfd
*, arelent
*, Elf32_Internal_Rela
*));
38 static bfd_reloc_status_type elf32_i860_relocate_splitn
39 PARAMS ((bfd
*, Elf_Internal_Rela
*, bfd_byte
*, bfd_vma
));
41 static bfd_reloc_status_type elf32_i860_relocate_pc16
42 PARAMS ((bfd
*, asection
*, Elf_Internal_Rela
*, bfd_byte
*, bfd_vma
));
44 static bfd_reloc_status_type elf32_i860_relocate_pc26
45 PARAMS ((bfd
*, asection
*, 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
));
58 static boolean elf32_i860_is_local_label_name
59 PARAMS ((bfd
*, const char *));
61 /* This howto table is preliminary. */
62 static reloc_howto_type elf32_i860_howto_table
[] =
64 /* This relocation does nothing. */
65 HOWTO (R_860_NONE
, /* type */
67 2, /* size (0 = byte, 1 = short, 2 = long) */
69 false, /* pc_relative */
71 complain_overflow_bitfield
, /* complain_on_overflow */
72 bfd_elf_generic_reloc
, /* special_function */
73 "R_860_NONE", /* name */
74 false, /* partial_inplace */
77 false), /* pcrel_offset */
79 /* A 32-bit absolute relocation. */
80 HOWTO (R_860_32
, /* type */
82 2, /* size (0 = byte, 1 = short, 2 = long) */
84 false, /* pc_relative */
86 complain_overflow_bitfield
, /* complain_on_overflow */
87 bfd_elf_generic_reloc
, /* special_function */
88 "R_860_32", /* name */
89 false, /* partial_inplace */
90 0xffffffff, /* src_mask */
91 0xffffffff, /* dst_mask */
92 false), /* pcrel_offset */
94 HOWTO (R_860_COPY
, /* type */
96 2, /* size (0 = byte, 1 = short, 2 = long) */
98 false, /* pc_relative */
100 complain_overflow_bitfield
, /* complain_on_overflow */
101 bfd_elf_generic_reloc
, /* special_function */
102 "R_860_COPY", /* name */
103 true, /* partial_inplace */
104 0xffffffff, /* src_mask */
105 0xffffffff, /* dst_mask */
106 false), /* pcrel_offset */
108 HOWTO (R_860_GLOB_DAT
, /* type */
110 2, /* size (0 = byte, 1 = short, 2 = long) */
112 false, /* pc_relative */
114 complain_overflow_bitfield
, /* complain_on_overflow */
115 bfd_elf_generic_reloc
, /* special_function */
116 "R_860_GLOB_DAT", /* name */
117 true, /* partial_inplace */
118 0xffffffff, /* src_mask */
119 0xffffffff, /* dst_mask */
120 false), /* pcrel_offset */
122 HOWTO (R_860_JUMP_SLOT
, /* type */
124 2, /* size (0 = byte, 1 = short, 2 = long) */
126 false, /* pc_relative */
128 complain_overflow_bitfield
, /* complain_on_overflow */
129 bfd_elf_generic_reloc
, /* special_function */
130 "R_860_JUMP_SLOT", /* name */
131 true, /* partial_inplace */
132 0xffffffff, /* src_mask */
133 0xffffffff, /* dst_mask */
134 false), /* pcrel_offset */
136 HOWTO (R_860_RELATIVE
, /* type */
138 2, /* size (0 = byte, 1 = short, 2 = long) */
140 false, /* pc_relative */
142 complain_overflow_bitfield
, /* complain_on_overflow */
143 bfd_elf_generic_reloc
, /* special_function */
144 "R_860_RELATIVE", /* name */
145 true, /* partial_inplace */
146 0xffffffff, /* src_mask */
147 0xffffffff, /* dst_mask */
148 false), /* pcrel_offset */
150 /* A 26-bit PC-relative relocation. */
151 HOWTO (R_860_PC26
, /* type */
153 2, /* size (0 = byte, 1 = short, 2 = long) */
155 true, /* pc_relative */
157 complain_overflow_bitfield
, /* complain_on_overflow */
158 bfd_elf_generic_reloc
, /* special_function */
159 "R_860_PC26", /* name */
160 false, /* partial_inplace */
161 0x3ffffff, /* src_mask */
162 0x3ffffff, /* dst_mask */
163 true), /* pcrel_offset */
165 HOWTO (R_860_PLT26
, /* type */
167 2, /* size (0 = byte, 1 = short, 2 = long) */
169 true, /* pc_relative */
171 complain_overflow_bitfield
, /* complain_on_overflow */
172 bfd_elf_generic_reloc
, /* special_function */
173 "R_860_PLT26", /* name */
174 true, /* partial_inplace */
175 0xffffffff, /* src_mask */
176 0xffffffff, /* dst_mask */
177 true), /* pcrel_offset */
179 /* A 16-bit PC-relative relocation. */
180 HOWTO (R_860_PC16
, /* type */
182 2, /* size (0 = byte, 1 = short, 2 = long) */
184 true, /* pc_relative */
186 complain_overflow_bitfield
, /* complain_on_overflow */
187 bfd_elf_generic_reloc
, /* special_function */
188 "R_860_PC16", /* name */
189 false, /* partial_inplace */
190 0x1f07ff, /* src_mask */
191 0x1f07ff, /* dst_mask */
192 true), /* pcrel_offset */
194 HOWTO (R_860_LOW0
, /* type */
196 2, /* size (0 = byte, 1 = short, 2 = long) */
198 false, /* pc_relative */
200 complain_overflow_dont
, /* complain_on_overflow */
201 bfd_elf_generic_reloc
, /* special_function */
202 "R_860_LOW0", /* name */
203 false, /* partial_inplace */
204 0xffff, /* src_mask */
205 0xffff, /* dst_mask */
206 false), /* pcrel_offset */
208 HOWTO (R_860_SPLIT0
, /* type */
210 2, /* size (0 = byte, 1 = short, 2 = long) */
212 false, /* pc_relative */
214 complain_overflow_dont
, /* complain_on_overflow */
215 bfd_elf_generic_reloc
, /* special_function */
216 "R_860_SPLIT0", /* name */
217 false, /* partial_inplace */
218 0x1f07ff, /* src_mask */
219 0x1f07ff, /* dst_mask */
220 false), /* pcrel_offset */
222 HOWTO (R_860_LOW1
, /* type */
224 2, /* size (0 = byte, 1 = short, 2 = long) */
226 false, /* pc_relative */
228 complain_overflow_dont
, /* complain_on_overflow */
229 bfd_elf_generic_reloc
, /* special_function */
230 "R_860_LOW1", /* name */
231 false, /* partial_inplace */
232 0xfffe, /* src_mask */
233 0xfffe, /* dst_mask */
234 false), /* pcrel_offset */
236 HOWTO (R_860_SPLIT1
, /* type */
238 2, /* size (0 = byte, 1 = short, 2 = long) */
240 false, /* pc_relative */
242 complain_overflow_dont
, /* complain_on_overflow */
243 bfd_elf_generic_reloc
, /* special_function */
244 "R_860_SPLIT1", /* name */
245 false, /* partial_inplace */
246 0x1f07fe, /* src_mask */
247 0x1f07fe, /* dst_mask */
248 false), /* pcrel_offset */
250 HOWTO (R_860_LOW2
, /* type */
252 2, /* size (0 = byte, 1 = short, 2 = long) */
254 false, /* pc_relative */
256 complain_overflow_dont
, /* complain_on_overflow */
257 bfd_elf_generic_reloc
, /* special_function */
258 "R_860_LOW2", /* name */
259 false, /* partial_inplace */
260 0xfffc, /* src_mask */
261 0xfffc, /* dst_mask */
262 false), /* pcrel_offset */
264 HOWTO (R_860_SPLIT2
, /* type */
266 2, /* size (0 = byte, 1 = short, 2 = long) */
268 false, /* pc_relative */
270 complain_overflow_dont
, /* complain_on_overflow */
271 bfd_elf_generic_reloc
, /* special_function */
272 "R_860_SPLIT2", /* name */
273 false, /* partial_inplace */
274 0x1f07fc, /* src_mask */
275 0x1f07fc, /* dst_mask */
276 false), /* pcrel_offset */
278 HOWTO (R_860_LOW3
, /* type */
280 2, /* size (0 = byte, 1 = short, 2 = long) */
282 false, /* pc_relative */
284 complain_overflow_dont
, /* complain_on_overflow */
285 bfd_elf_generic_reloc
, /* special_function */
286 "R_860_LOW3", /* name */
287 false, /* partial_inplace */
288 0xfff8, /* src_mask */
289 0xfff8, /* dst_mask */
290 false), /* pcrel_offset */
292 HOWTO (R_860_LOGOT0
, /* type */
294 2, /* size (0 = byte, 1 = short, 2 = long) */
296 false, /* pc_relative */
298 complain_overflow_dont
, /* complain_on_overflow */
299 bfd_elf_generic_reloc
, /* special_function */
300 "R_860_LOGOT0", /* name */
301 false, /* partial_inplace */
303 0xffff, /* dst_mask */
304 true), /* pcrel_offset */
306 HOWTO (R_860_SPGOT0
, /* type */
308 2, /* size (0 = byte, 1 = short, 2 = long) */
310 false, /* pc_relative */
312 complain_overflow_dont
, /* complain_on_overflow */
313 bfd_elf_generic_reloc
, /* special_function */
314 "R_860_SPGOT0", /* name */
315 false, /* partial_inplace */
317 0xffff, /* dst_mask */
318 true), /* pcrel_offset */
320 HOWTO (R_860_LOGOT1
, /* type */
322 2, /* size (0 = byte, 1 = short, 2 = long) */
324 false, /* pc_relative */
326 complain_overflow_dont
, /* complain_on_overflow */
327 bfd_elf_generic_reloc
, /* special_function */
328 "R_860_LOGOT1", /* name */
329 false, /* partial_inplace */
331 0xffff, /* dst_mask */
332 true), /* pcrel_offset */
334 HOWTO (R_860_SPGOT1
, /* type */
336 2, /* size (0 = byte, 1 = short, 2 = long) */
338 false, /* pc_relative */
340 complain_overflow_dont
, /* complain_on_overflow */
341 bfd_elf_generic_reloc
, /* special_function */
342 "R_860_SPGOT1", /* name */
343 false, /* partial_inplace */
345 0xffff, /* dst_mask */
346 true), /* pcrel_offset */
348 HOWTO (R_860_LOGOTOFF0
, /* type */
350 2, /* size (0 = byte, 1 = short, 2 = long) */
352 false, /* pc_relative */
354 complain_overflow_dont
, /* complain_on_overflow */
355 bfd_elf_generic_reloc
, /* special_function */
356 "R_860_LOGOTOFF0", /* name */
357 true, /* partial_inplace */
358 0xffffffff, /* src_mask */
359 0xffffffff, /* dst_mask */
360 false), /* pcrel_offset */
362 HOWTO (R_860_SPGOTOFF0
, /* type */
364 2, /* size (0 = byte, 1 = short, 2 = long) */
366 false, /* pc_relative */
368 complain_overflow_dont
, /* complain_on_overflow */
369 bfd_elf_generic_reloc
, /* special_function */
370 "R_860_SPGOTOFF0", /* name */
371 true, /* partial_inplace */
372 0xffffffff, /* src_mask */
373 0xffffffff, /* dst_mask */
374 false), /* pcrel_offset */
376 HOWTO (R_860_LOGOTOFF1
, /* type */
378 2, /* size (0 = byte, 1 = short, 2 = long) */
380 false, /* pc_relative */
382 complain_overflow_dont
, /* complain_on_overflow */
383 bfd_elf_generic_reloc
, /* special_function */
384 "R_860_LOGOTOFF1", /* name */
385 true, /* partial_inplace */
386 0xffffffff, /* src_mask */
387 0xffffffff, /* dst_mask */
388 false), /* pcrel_offset */
390 HOWTO (R_860_SPGOTOFF1
, /* type */
392 2, /* size (0 = byte, 1 = short, 2 = long) */
394 false, /* pc_relative */
396 complain_overflow_dont
, /* complain_on_overflow */
397 bfd_elf_generic_reloc
, /* special_function */
398 "R_860_SPGOTOFF1", /* name */
399 true, /* partial_inplace */
400 0xffffffff, /* src_mask */
401 0xffffffff, /* dst_mask */
402 false), /* pcrel_offset */
404 HOWTO (R_860_LOGOTOFF2
, /* type */
406 2, /* size (0 = byte, 1 = short, 2 = long) */
408 false, /* pc_relative */
410 complain_overflow_dont
, /* complain_on_overflow */
411 bfd_elf_generic_reloc
, /* special_function */
412 "R_860_LOGOTOFF2", /* name */
413 true, /* partial_inplace */
414 0xffffffff, /* src_mask */
415 0xffffffff, /* dst_mask */
416 false), /* pcrel_offset */
418 HOWTO (R_860_LOGOTOFF3
, /* type */
420 2, /* size (0 = byte, 1 = short, 2 = long) */
422 false, /* pc_relative */
424 complain_overflow_dont
, /* complain_on_overflow */
425 bfd_elf_generic_reloc
, /* special_function */
426 "R_860_LOGOTOFF3", /* name */
427 true, /* partial_inplace */
428 0xffffffff, /* src_mask */
429 0xffffffff, /* dst_mask */
430 false), /* pcrel_offset */
432 HOWTO (R_860_LOPC
, /* type */
434 2, /* size (0 = byte, 1 = short, 2 = long) */
436 true, /* pc_relative */
438 complain_overflow_bitfield
, /* complain_on_overflow */
439 bfd_elf_generic_reloc
, /* special_function */
440 "R_860_LOPC", /* name */
441 false, /* partial_inplace */
442 0xffff, /* src_mask */
443 0xffff, /* dst_mask */
444 true), /* pcrel_offset */
446 HOWTO (R_860_HIGHADJ
, /* type */
448 2, /* size (0 = byte, 1 = short, 2 = long) */
450 false, /* pc_relative */
452 complain_overflow_dont
, /* complain_on_overflow */
453 bfd_elf_generic_reloc
, /* special_function */
454 "R_860_HIGHADJ", /* name */
455 false, /* partial_inplace */
456 0xffff, /* src_mask */
457 0xffff, /* dst_mask */
458 false), /* pcrel_offset */
460 HOWTO (R_860_HAGOT
, /* type */
462 2, /* size (0 = byte, 1 = short, 2 = long) */
464 false, /* pc_relative */
466 complain_overflow_dont
, /* complain_on_overflow */
467 bfd_elf_generic_reloc
, /* special_function */
468 "R_860_HAGOT", /* name */
469 false, /* partial_inplace */
471 0xffff, /* dst_mask */
472 true), /* pcrel_offset */
474 HOWTO (R_860_HAGOTOFF
, /* type */
476 2, /* size (0 = byte, 1 = short, 2 = long) */
478 false, /* pc_relative */
480 complain_overflow_dont
, /* complain_on_overflow */
481 bfd_elf_generic_reloc
, /* special_function */
482 "R_860_HAGOTOFF", /* name */
483 true, /* partial_inplace */
484 0xffffffff, /* src_mask */
485 0xffffffff, /* dst_mask */
486 false), /* pcrel_offset */
488 HOWTO (R_860_HAPC
, /* type */
490 2, /* size (0 = byte, 1 = short, 2 = long) */
492 true, /* pc_relative */
494 complain_overflow_bitfield
, /* complain_on_overflow */
495 bfd_elf_generic_reloc
, /* special_function */
496 "R_860_HAPC", /* name */
497 false, /* partial_inplace */
498 0xffff, /* src_mask */
499 0xffff, /* dst_mask */
500 true), /* pcrel_offset */
502 HOWTO (R_860_HIGH
, /* type */
504 2, /* size (0 = byte, 1 = short, 2 = long) */
506 false, /* pc_relative */
508 complain_overflow_dont
, /* complain_on_overflow */
509 bfd_elf_generic_reloc
, /* special_function */
510 "R_860_HIGH", /* name */
511 false, /* partial_inplace */
512 0xffff, /* src_mask */
513 0xffff, /* dst_mask */
514 false), /* pcrel_offset */
516 HOWTO (R_860_HIGOT
, /* type */
518 2, /* size (0 = byte, 1 = short, 2 = long) */
520 false, /* pc_relative */
522 complain_overflow_dont
, /* complain_on_overflow */
523 bfd_elf_generic_reloc
, /* special_function */
524 "R_860_HIGOT", /* name */
525 false, /* partial_inplace */
527 0xffff, /* dst_mask */
528 true), /* pcrel_offset */
530 HOWTO (R_860_HIGOTOFF
, /* type */
532 2, /* size (0 = byte, 1 = short, 2 = long) */
534 false, /* pc_relative */
536 complain_overflow_dont
, /* complain_on_overflow */
537 bfd_elf_generic_reloc
, /* special_function */
538 "R_860_HIGOTOFF", /* name */
539 true, /* partial_inplace */
540 0xffffffff, /* src_mask */
541 0xffffffff, /* dst_mask */
542 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
;
572 /* Given a BFD reloc, return the matching HOWTO structure. */
573 static reloc_howto_type
*
574 elf32_i860_reloc_type_lookup (abfd
, code
)
575 bfd
* abfd ATTRIBUTE_UNUSED
;
576 bfd_reloc_code_real_type code
;
588 case BFD_RELOC_860_COPY
:
591 case BFD_RELOC_860_GLOB_DAT
:
592 rtype
= R_860_GLOB_DAT
;
594 case BFD_RELOC_860_JUMP_SLOT
:
595 rtype
= R_860_JUMP_SLOT
;
597 case BFD_RELOC_860_RELATIVE
:
598 rtype
= R_860_RELATIVE
;
600 case BFD_RELOC_860_PC26
:
603 case BFD_RELOC_860_PLT26
:
606 case BFD_RELOC_860_PC16
:
609 case BFD_RELOC_860_LOW0
:
612 case BFD_RELOC_860_SPLIT0
:
613 rtype
= R_860_SPLIT0
;
615 case BFD_RELOC_860_LOW1
:
618 case BFD_RELOC_860_SPLIT1
:
619 rtype
= R_860_SPLIT1
;
621 case BFD_RELOC_860_LOW2
:
624 case BFD_RELOC_860_SPLIT2
:
625 rtype
= R_860_SPLIT2
;
627 case BFD_RELOC_860_LOW3
:
630 case BFD_RELOC_860_LOGOT0
:
631 rtype
= R_860_LOGOT0
;
633 case BFD_RELOC_860_SPGOT0
:
634 rtype
= R_860_SPGOT0
;
636 case BFD_RELOC_860_LOGOT1
:
637 rtype
= R_860_LOGOT1
;
639 case BFD_RELOC_860_SPGOT1
:
640 rtype
= R_860_SPGOT1
;
642 case BFD_RELOC_860_LOGOTOFF0
:
643 rtype
= R_860_LOGOTOFF0
;
645 case BFD_RELOC_860_SPGOTOFF0
:
646 rtype
= R_860_SPGOTOFF0
;
648 case BFD_RELOC_860_LOGOTOFF1
:
649 rtype
= R_860_LOGOTOFF1
;
651 case BFD_RELOC_860_SPGOTOFF1
:
652 rtype
= R_860_SPGOTOFF1
;
654 case BFD_RELOC_860_LOGOTOFF2
:
655 rtype
= R_860_LOGOTOFF2
;
657 case BFD_RELOC_860_LOGOTOFF3
:
658 rtype
= R_860_LOGOTOFF3
;
660 case BFD_RELOC_860_LOPC
:
663 case BFD_RELOC_860_HIGHADJ
:
664 rtype
= R_860_HIGHADJ
;
666 case BFD_RELOC_860_HAGOT
:
669 case BFD_RELOC_860_HAGOTOFF
:
670 rtype
= R_860_HAGOTOFF
;
672 case BFD_RELOC_860_HAPC
:
675 case BFD_RELOC_860_HIGH
:
678 case BFD_RELOC_860_HIGOT
:
681 case BFD_RELOC_860_HIGOTOFF
:
682 rtype
= R_860_HIGOTOFF
;
688 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
;
699 = lookup_howto ((unsigned) ELF32_R_TYPE (elf_reloc
->r_info
));
702 /* Specialized relocation handler for R_860_SPLITn. These relocations
703 involves a 16-bit field that is split into two contiguous parts. */
704 static bfd_reloc_status_type
705 elf32_i860_relocate_splitn (input_bfd
, rello
, contents
, value
)
707 Elf_Internal_Rela
*rello
;
712 reloc_howto_type
*howto
;
713 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rello
->r_info
));
714 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
717 value
+= rello
->r_addend
;
719 /* Separate the fields and insert. */
720 value
= (((value
& 0xf8) << 5) | (value
& 0x7ff)) & howto
->dst_mask
;
721 insn
= (insn
& ~howto
->dst_mask
) | value
;
723 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
727 /* Specialized relocation handler for R_860_PC16. This relocation
728 involves a 16-bit, PC-relative field that is split into two contiguous
730 static bfd_reloc_status_type
731 elf32_i860_relocate_pc16 (input_bfd
, input_section
, rello
, contents
, value
)
733 asection
*input_section
;
734 Elf_Internal_Rela
*rello
;
739 reloc_howto_type
*howto
;
740 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rello
->r_info
));
741 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
743 /* Adjust for PC-relative relocation. */
744 value
-= (input_section
->output_section
->vma
745 + input_section
->output_offset
);
746 value
-= rello
->r_offset
;
749 value
+= rello
->r_addend
;
751 /* Separate the fields and insert. */
752 value
= (((value
& 0xf8) << 5) | (value
& 0x7ff)) & howto
->dst_mask
;
753 insn
= (insn
& ~howto
->dst_mask
) | value
;
755 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
760 /* Specialized relocation handler for R_860_PC26. This relocation
761 involves a 26-bit, PC-relative field which must be adjusted by 4. */
762 static bfd_reloc_status_type
763 elf32_i860_relocate_pc26 (input_bfd
, input_section
, rello
, contents
, value
)
765 asection
*input_section
;
766 Elf_Internal_Rela
*rello
;
771 reloc_howto_type
*howto
;
772 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rello
->r_info
));
773 insn
= bfd_get_32 (input_bfd
, contents
+ rello
->r_offset
);
775 /* Adjust for PC-relative relocation. */
776 value
-= (input_section
->output_section
->vma
777 + input_section
->output_offset
);
778 value
-= rello
->r_offset
;
781 value
+= rello
->r_addend
;
783 /* Adjust value by 4 and insert the field. */
784 value
= ((value
- 4) >> howto
->rightshift
) & howto
->dst_mask
;
785 insn
= (insn
& ~howto
->dst_mask
) | value
;
787 bfd_put_32 (input_bfd
, insn
, contents
+ rello
->r_offset
);
792 /* Specialized relocation handler for R_860_HIGHADJ. */
793 static bfd_reloc_status_type
794 elf32_i860_relocate_highadj (input_bfd
, rel
, contents
, value
)
796 Elf_Internal_Rela
*rel
;
802 insn
= bfd_get_32 (input_bfd
, contents
+ rel
->r_offset
);
804 value
+= ((rel
->r_addend
& 0x8000) << 1);
805 value
+= rel
->r_addend
;
806 value
= ((value
>> 16) & 0xffff);
808 insn
= (insn
& 0xffff0000) | value
;
810 bfd_put_32 (input_bfd
, insn
, contents
+ rel
->r_offset
);
814 /* Perform a single relocation. By default we use the standard BFD
815 routines. However, we handle some specially. */
816 static bfd_reloc_status_type
817 i860_final_link_relocate (howto
, input_bfd
, input_section
, contents
, rel
, relocation
)
818 reloc_howto_type
* howto
;
820 asection
* input_section
;
822 Elf_Internal_Rela
* rel
;
825 return _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
826 contents
, rel
->r_offset
, relocation
,
830 /* Relocate an i860 ELF section.
832 This is boiler-plate code copied from fr30.
833 There is some attempt to make this function usable for many architectures,
834 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
835 if only to serve as a learning tool.
837 The RELOCATE_SECTION function is called by the new ELF backend linker
838 to handle the relocations for a section.
840 The relocs are always passed as Rela structures; if the section
841 actually uses Rel structures, the r_addend field will always be
844 This function is responsible for adjusting the section contents as
845 necessary, and (if using Rela relocs and generating a relocateable
846 output file) adjusting the reloc addend as necessary.
848 This function does not have to worry about setting the reloc
849 address or the reloc symbol index.
851 LOCAL_SYMS is a pointer to the swapped in local symbols.
853 LOCAL_SECTIONS is an array giving the section in the input file
854 corresponding to the st_shndx field of each local symbol.
856 The global hash table entry for the global symbols can be found
857 via elf_sym_hashes (input_bfd).
859 When generating relocateable output, this function must handle
860 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
861 going to be the section symbol corresponding to the output
862 section, which means that the addend must be adjusted
865 elf32_i860_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
866 contents
, relocs
, local_syms
, local_sections
)
867 bfd
* output_bfd ATTRIBUTE_UNUSED
;
868 struct bfd_link_info
* info
;
870 asection
* input_section
;
872 Elf_Internal_Rela
* relocs
;
873 Elf_Internal_Sym
* local_syms
;
874 asection
** local_sections
;
876 Elf_Internal_Shdr
* symtab_hdr
;
877 struct elf_link_hash_entry
** sym_hashes
;
878 Elf_Internal_Rela
* rel
;
879 Elf_Internal_Rela
* relend
;
881 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
882 sym_hashes
= elf_sym_hashes (input_bfd
);
883 relend
= relocs
+ input_section
->reloc_count
;
885 for (rel
= relocs
; rel
< relend
; rel
++)
887 reloc_howto_type
* howto
;
888 unsigned long r_symndx
;
889 Elf_Internal_Sym
* sym
;
891 struct elf_link_hash_entry
* h
;
893 bfd_reloc_status_type r
;
894 const char * name
= NULL
;
897 r_type
= ELF32_R_TYPE (rel
->r_info
);
900 if ( r_type
== R_860_GNU_VTINHERIT
901 || r_type
== R_860_GNU_VTENTRY
)
905 r_symndx
= ELF32_R_SYM (rel
->r_info
);
907 if (info
->relocateable
)
909 /* This is a relocateable link. We don't have to change
910 anything, unless the reloc is against a section symbol,
911 in which case we have to adjust according to where the
912 section symbol winds up in the output section. */
913 if (r_symndx
< symtab_hdr
->sh_info
)
915 sym
= local_syms
+ r_symndx
;
917 if (ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
919 sec
= local_sections
[r_symndx
];
920 rel
->r_addend
+= sec
->output_offset
+ sym
->st_value
;
927 /* This is a final link. */
928 howto
= lookup_howto ((unsigned) ELF32_R_TYPE (rel
->r_info
));
933 if (r_symndx
< symtab_hdr
->sh_info
)
935 sym
= local_syms
+ r_symndx
;
936 sec
= local_sections
[r_symndx
];
937 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, sec
, rel
);
939 name
= bfd_elf_string_from_elf_section
940 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
941 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
945 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
947 while (h
->root
.type
== bfd_link_hash_indirect
948 || h
->root
.type
== bfd_link_hash_warning
)
949 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
951 name
= h
->root
.root
.string
;
953 if (h
->root
.type
== bfd_link_hash_defined
954 || h
->root
.type
== bfd_link_hash_defweak
)
956 sec
= h
->root
.u
.def
.section
;
957 relocation
= (h
->root
.u
.def
.value
958 + sec
->output_section
->vma
959 + sec
->output_offset
);
961 else if (h
->root
.type
== bfd_link_hash_undefweak
)
967 if (! ((*info
->callbacks
->undefined_symbol
)
968 (info
, h
->root
.root
.string
, input_bfd
,
969 input_section
, rel
->r_offset
, true)))
978 r
= i860_final_link_relocate (howto
, input_bfd
, input_section
,
979 contents
, rel
, relocation
);
983 r
= elf32_i860_relocate_highadj (input_bfd
, rel
, contents
,
988 r
= elf32_i860_relocate_pc16 (input_bfd
, input_section
, rel
,
989 contents
, relocation
);
993 r
= elf32_i860_relocate_pc26 (input_bfd
, input_section
, rel
,
994 contents
, relocation
);
1000 r
= elf32_i860_relocate_splitn (input_bfd
, rel
, contents
,
1004 /* We do not yet handle GOT/PLT/Dynamic relocations. */
1006 case R_860_GLOB_DAT
:
1007 case R_860_JUMP_SLOT
:
1008 case R_860_RELATIVE
:
1014 case R_860_LOGOTOFF0
:
1015 case R_860_SPGOTOFF0
:
1016 case R_860_LOGOTOFF1
:
1017 case R_860_SPGOTOFF1
:
1018 case R_860_LOGOTOFF2
:
1019 case R_860_LOGOTOFF3
:
1022 case R_860_HAGOTOFF
:
1025 case R_860_HIGOTOFF
:
1026 r
= bfd_reloc_notsupported
;
1030 if (r
!= bfd_reloc_ok
)
1032 const char * msg
= (const char *) NULL
;
1036 case bfd_reloc_overflow
:
1037 r
= info
->callbacks
->reloc_overflow
1038 (info
, name
, howto
->name
, (bfd_vma
) 0,
1039 input_bfd
, input_section
, rel
->r_offset
);
1042 case bfd_reloc_undefined
:
1043 r
= info
->callbacks
->undefined_symbol
1044 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, true);
1047 case bfd_reloc_outofrange
:
1048 msg
= _("internal error: out of range error");
1051 case bfd_reloc_notsupported
:
1052 msg
= _("internal error: unsupported relocation error");
1055 case bfd_reloc_dangerous
:
1056 msg
= _("internal error: dangerous relocation");
1060 msg
= _("internal error: unknown error");
1065 r
= info
->callbacks
->warning
1066 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
1076 /* Return whether a symbol name implies a local label. SVR4/860 compilers
1077 generate labels of the form ".ep.function_name" to denote the end of a
1078 function prolog. These should be local.
1079 ??? Do any other SVR4 compilers have this convention? If so, this should
1080 be added to the generic routine. */
1082 elf32_i860_is_local_label_name (abfd
, name
)
1086 if (name
[0] == '.' && name
[1] == 'e' && name
[2] == 'p' && name
[3] == '.')
1089 return _bfd_elf_is_local_label_name (abfd
, name
);
1092 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1093 #define TARGET_BIG_NAME "elf32-i860"
1094 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1095 #define TARGET_LITTLE_NAME "elf32-i860-little"
1096 #define ELF_ARCH bfd_arch_i860
1097 #define ELF_MACHINE_CODE EM_860
1098 #define ELF_MAXPAGESIZE 4096
1100 #define elf_info_to_howto_rel NULL
1101 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1102 #define elf_backend_relocate_section elf32_i860_relocate_section
1103 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1104 #define bfd_elf32_bfd_is_local_label_name elf32_i860_is_local_label_name
1106 #include "elf32-target.h"