2000-09-12 Philip Blundell <philb@gnu.org>
[binutils.git] / bfd / elf32-i860.c
bloba0668da16633de74dda8f96f9064fa6ddaf5ea4a
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. */
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/i860.h"
29 /* Prototypes. */
30 static reloc_howto_type *lookup_howto
31 PARAMS ((unsigned int));
33 static reloc_howto_type *elf32_i860_reloc_type_lookup
34 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
36 static void elf32_i860_info_to_howto_rela
37 PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
39 static bfd_reloc_status_type elf32_i860_relocate_splitn
40 PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
42 static bfd_reloc_status_type elf32_i860_relocate_pc16
43 PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
45 static bfd_reloc_status_type elf32_i860_relocate_pc26
46 PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
48 static bfd_reloc_status_type elf32_i860_relocate_highadj
49 PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
51 static boolean elf32_i860_relocate_section
52 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
53 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
55 static bfd_reloc_status_type i860_final_link_relocate
56 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
57 Elf_Internal_Rela *, bfd_vma));
59 static boolean elf32_i860_is_local_label_name
60 PARAMS ((bfd *, const char *));
64 /* This howto table is preliminary. */
65 static reloc_howto_type elf32_i860_howto_table [] =
67 /* This relocation does nothing. */
68 HOWTO (R_860_NONE, /* type */
69 0, /* rightshift */
70 2, /* size (0 = byte, 1 = short, 2 = long) */
71 32, /* bitsize */
72 false, /* pc_relative */
73 0, /* bitpos */
74 complain_overflow_bitfield, /* complain_on_overflow */
75 bfd_elf_generic_reloc, /* special_function */
76 "R_860_NONE", /* name */
77 false, /* partial_inplace */
78 0, /* src_mask */
79 0, /* dst_mask */
80 false), /* pcrel_offset */
82 /* A 32-bit absolute relocation. */
83 HOWTO (R_860_32, /* type */
84 0, /* rightshift */
85 2, /* size (0 = byte, 1 = short, 2 = long) */
86 32, /* bitsize */
87 false, /* pc_relative */
88 0, /* bitpos */
89 complain_overflow_bitfield, /* complain_on_overflow */
90 bfd_elf_generic_reloc, /* special_function */
91 "R_860_32", /* name */
92 false, /* partial_inplace */
93 0xffffffff, /* src_mask */
94 0xffffffff, /* dst_mask */
95 false), /* pcrel_offset */
97 HOWTO (R_860_COPY, /* type */
98 0, /* rightshift */
99 2, /* size (0 = byte, 1 = short, 2 = long) */
100 32, /* bitsize */
101 false, /* pc_relative */
102 0, /* bitpos */
103 complain_overflow_bitfield, /* complain_on_overflow */
104 bfd_elf_generic_reloc, /* special_function */
105 "R_860_COPY", /* name */
106 true, /* partial_inplace */
107 0xffffffff, /* src_mask */
108 0xffffffff, /* dst_mask */
109 false), /* pcrel_offset */
111 HOWTO (R_860_GLOB_DAT, /* type */
112 0, /* rightshift */
113 2, /* size (0 = byte, 1 = short, 2 = long) */
114 32, /* bitsize */
115 false, /* pc_relative */
116 0, /* bitpos */
117 complain_overflow_bitfield, /* complain_on_overflow */
118 bfd_elf_generic_reloc, /* special_function */
119 "R_860_GLOB_DAT", /* name */
120 true, /* partial_inplace */
121 0xffffffff, /* src_mask */
122 0xffffffff, /* dst_mask */
123 false), /* pcrel_offset */
125 HOWTO (R_860_JUMP_SLOT, /* type */
126 0, /* rightshift */
127 2, /* size (0 = byte, 1 = short, 2 = long) */
128 32, /* bitsize */
129 false, /* pc_relative */
130 0, /* bitpos */
131 complain_overflow_bitfield, /* complain_on_overflow */
132 bfd_elf_generic_reloc, /* special_function */
133 "R_860_JUMP_SLOT", /* name */
134 true, /* partial_inplace */
135 0xffffffff, /* src_mask */
136 0xffffffff, /* dst_mask */
137 false), /* pcrel_offset */
139 HOWTO (R_860_RELATIVE, /* type */
140 0, /* rightshift */
141 2, /* size (0 = byte, 1 = short, 2 = long) */
142 32, /* bitsize */
143 false, /* pc_relative */
144 0, /* bitpos */
145 complain_overflow_bitfield, /* complain_on_overflow */
146 bfd_elf_generic_reloc, /* special_function */
147 "R_860_RELATIVE", /* name */
148 true, /* partial_inplace */
149 0xffffffff, /* src_mask */
150 0xffffffff, /* dst_mask */
151 false), /* pcrel_offset */
153 /* A 26-bit PC-relative relocation. */
154 HOWTO (R_860_PC26, /* type */
155 2, /* rightshift */
156 2, /* size (0 = byte, 1 = short, 2 = long) */
157 26, /* bitsize */
158 true, /* pc_relative */
159 0, /* bitpos */
160 complain_overflow_bitfield, /* complain_on_overflow */
161 bfd_elf_generic_reloc, /* special_function */
162 "R_860_PC26", /* name */
163 false, /* partial_inplace */
164 0x3ffffff, /* src_mask */
165 0x3ffffff, /* dst_mask */
166 true), /* pcrel_offset */
168 HOWTO (R_860_PLT26, /* type */
169 0, /* rightshift */
170 2, /* size (0 = byte, 1 = short, 2 = long) */
171 26, /* bitsize */
172 true, /* pc_relative */
173 0, /* bitpos */
174 complain_overflow_bitfield, /* complain_on_overflow */
175 bfd_elf_generic_reloc, /* special_function */
176 "R_860_PLT26", /* name */
177 true, /* partial_inplace */
178 0xffffffff, /* src_mask */
179 0xffffffff, /* dst_mask */
180 true), /* pcrel_offset */
182 /* A 16-bit PC-relative relocation. */
183 HOWTO (R_860_PC16, /* type */
184 2, /* rightshift */
185 2, /* size (0 = byte, 1 = short, 2 = long) */
186 16, /* bitsize */
187 true, /* pc_relative */
188 0, /* bitpos */
189 complain_overflow_bitfield, /* complain_on_overflow */
190 bfd_elf_generic_reloc, /* special_function */
191 "R_860_PC16", /* name */
192 false, /* partial_inplace */
193 0x1f07ff, /* src_mask */
194 0x1f07ff, /* dst_mask */
195 true), /* pcrel_offset */
197 HOWTO (R_860_LOW0, /* type */
198 0, /* rightshift */
199 2, /* size (0 = byte, 1 = short, 2 = long) */
200 16, /* bitsize */
201 false, /* pc_relative */
202 0, /* bitpos */
203 complain_overflow_dont, /* complain_on_overflow */
204 bfd_elf_generic_reloc, /* special_function */
205 "R_860_LOW0", /* name */
206 false, /* partial_inplace */
207 0xffff, /* src_mask */
208 0xffff, /* dst_mask */
209 false), /* pcrel_offset */
211 HOWTO (R_860_SPLIT0, /* type */
212 0, /* rightshift */
213 2, /* size (0 = byte, 1 = short, 2 = long) */
214 16, /* bitsize */
215 false, /* pc_relative */
216 0, /* bitpos */
217 complain_overflow_dont, /* complain_on_overflow */
218 bfd_elf_generic_reloc, /* special_function */
219 "R_860_SPLIT0", /* name */
220 false, /* partial_inplace */
221 0x1f07ff, /* src_mask */
222 0x1f07ff, /* dst_mask */
223 false), /* pcrel_offset */
225 HOWTO (R_860_LOW1, /* type */
226 0, /* rightshift */
227 2, /* size (0 = byte, 1 = short, 2 = long) */
228 16, /* bitsize */
229 false, /* pc_relative */
230 0, /* bitpos */
231 complain_overflow_dont, /* complain_on_overflow */
232 bfd_elf_generic_reloc, /* special_function */
233 "R_860_LOW1", /* name */
234 false, /* partial_inplace */
235 0xfffe, /* src_mask */
236 0xfffe, /* dst_mask */
237 false), /* pcrel_offset */
239 HOWTO (R_860_SPLIT1, /* type */
240 0, /* rightshift */
241 2, /* size (0 = byte, 1 = short, 2 = long) */
242 16, /* bitsize */
243 false, /* pc_relative */
244 0, /* bitpos */
245 complain_overflow_dont, /* complain_on_overflow */
246 bfd_elf_generic_reloc, /* special_function */
247 "R_860_SPLIT1", /* name */
248 false, /* partial_inplace */
249 0x1f07fe, /* src_mask */
250 0x1f07fe, /* dst_mask */
251 false), /* pcrel_offset */
253 HOWTO (R_860_LOW2, /* type */
254 0, /* rightshift */
255 2, /* size (0 = byte, 1 = short, 2 = long) */
256 16, /* bitsize */
257 false, /* pc_relative */
258 0, /* bitpos */
259 complain_overflow_dont, /* complain_on_overflow */
260 bfd_elf_generic_reloc, /* special_function */
261 "R_860_LOW2", /* name */
262 false, /* partial_inplace */
263 0xfffc, /* src_mask */
264 0xfffc, /* dst_mask */
265 false), /* pcrel_offset */
267 HOWTO (R_860_SPLIT2, /* type */
268 0, /* rightshift */
269 2, /* size (0 = byte, 1 = short, 2 = long) */
270 16, /* bitsize */
271 false, /* pc_relative */
272 0, /* bitpos */
273 complain_overflow_dont, /* complain_on_overflow */
274 bfd_elf_generic_reloc, /* special_function */
275 "R_860_SPLIT2", /* name */
276 false, /* partial_inplace */
277 0x1f07fc, /* src_mask */
278 0x1f07fc, /* dst_mask */
279 false), /* pcrel_offset */
281 HOWTO (R_860_LOW3, /* type */
282 0, /* rightshift */
283 2, /* size (0 = byte, 1 = short, 2 = long) */
284 16, /* bitsize */
285 false, /* pc_relative */
286 0, /* bitpos */
287 complain_overflow_dont, /* complain_on_overflow */
288 bfd_elf_generic_reloc, /* special_function */
289 "R_860_LOW3", /* name */
290 false, /* partial_inplace */
291 0xfff8, /* src_mask */
292 0xfff8, /* dst_mask */
293 false), /* pcrel_offset */
295 HOWTO (R_860_LOGOT0, /* type */
296 0, /* rightshift */
297 2, /* size (0 = byte, 1 = short, 2 = long) */
298 16, /* bitsize */
299 false, /* pc_relative */
300 0, /* bitpos */
301 complain_overflow_dont, /* complain_on_overflow */
302 bfd_elf_generic_reloc, /* special_function */
303 "R_860_LOGOT0", /* name */
304 false, /* partial_inplace */
305 0, /* src_mask */
306 0xffff, /* dst_mask */
307 true), /* pcrel_offset */
309 HOWTO (R_860_SPGOT0, /* type */
310 0, /* rightshift */
311 2, /* size (0 = byte, 1 = short, 2 = long) */
312 16, /* bitsize */
313 false, /* pc_relative */
314 0, /* bitpos */
315 complain_overflow_dont, /* complain_on_overflow */
316 bfd_elf_generic_reloc, /* special_function */
317 "R_860_SPGOT0", /* name */
318 false, /* partial_inplace */
319 0, /* src_mask */
320 0xffff, /* dst_mask */
321 true), /* pcrel_offset */
323 HOWTO (R_860_LOGOT1, /* type */
324 0, /* rightshift */
325 2, /* size (0 = byte, 1 = short, 2 = long) */
326 16, /* bitsize */
327 false, /* pc_relative */
328 0, /* bitpos */
329 complain_overflow_dont, /* complain_on_overflow */
330 bfd_elf_generic_reloc, /* special_function */
331 "R_860_LOGOT1", /* name */
332 false, /* partial_inplace */
333 0, /* src_mask */
334 0xffff, /* dst_mask */
335 true), /* pcrel_offset */
337 HOWTO (R_860_SPGOT1, /* type */
338 0, /* rightshift */
339 2, /* size (0 = byte, 1 = short, 2 = long) */
340 16, /* bitsize */
341 false, /* pc_relative */
342 0, /* bitpos */
343 complain_overflow_dont, /* complain_on_overflow */
344 bfd_elf_generic_reloc, /* special_function */
345 "R_860_SPGOT1", /* name */
346 false, /* partial_inplace */
347 0, /* src_mask */
348 0xffff, /* dst_mask */
349 true), /* pcrel_offset */
351 HOWTO (R_860_LOGOTOFF0, /* type */
352 0, /* rightshift */
353 2, /* size (0 = byte, 1 = short, 2 = long) */
354 32, /* bitsize */
355 false, /* pc_relative */
356 0, /* bitpos */
357 complain_overflow_dont, /* complain_on_overflow */
358 bfd_elf_generic_reloc, /* special_function */
359 "R_860_LOGOTOFF0", /* name */
360 true, /* partial_inplace */
361 0xffffffff, /* src_mask */
362 0xffffffff, /* dst_mask */
363 false), /* pcrel_offset */
365 HOWTO (R_860_SPGOTOFF0, /* type */
366 0, /* rightshift */
367 2, /* size (0 = byte, 1 = short, 2 = long) */
368 32, /* bitsize */
369 false, /* pc_relative */
370 0, /* bitpos */
371 complain_overflow_dont, /* complain_on_overflow */
372 bfd_elf_generic_reloc, /* special_function */
373 "R_860_SPGOTOFF0", /* name */
374 true, /* partial_inplace */
375 0xffffffff, /* src_mask */
376 0xffffffff, /* dst_mask */
377 false), /* pcrel_offset */
379 HOWTO (R_860_LOGOTOFF1, /* type */
380 0, /* rightshift */
381 2, /* size (0 = byte, 1 = short, 2 = long) */
382 32, /* bitsize */
383 false, /* pc_relative */
384 0, /* bitpos */
385 complain_overflow_dont, /* complain_on_overflow */
386 bfd_elf_generic_reloc, /* special_function */
387 "R_860_LOGOTOFF1", /* name */
388 true, /* partial_inplace */
389 0xffffffff, /* src_mask */
390 0xffffffff, /* dst_mask */
391 false), /* pcrel_offset */
393 HOWTO (R_860_SPGOTOFF1, /* type */
394 0, /* rightshift */
395 2, /* size (0 = byte, 1 = short, 2 = long) */
396 32, /* bitsize */
397 false, /* pc_relative */
398 0, /* bitpos */
399 complain_overflow_dont, /* complain_on_overflow */
400 bfd_elf_generic_reloc, /* special_function */
401 "R_860_SPGOTOFF1", /* name */
402 true, /* partial_inplace */
403 0xffffffff, /* src_mask */
404 0xffffffff, /* dst_mask */
405 false), /* pcrel_offset */
407 HOWTO (R_860_LOGOTOFF2, /* type */
408 0, /* rightshift */
409 2, /* size (0 = byte, 1 = short, 2 = long) */
410 32, /* bitsize */
411 false, /* pc_relative */
412 0, /* bitpos */
413 complain_overflow_dont, /* complain_on_overflow */
414 bfd_elf_generic_reloc, /* special_function */
415 "R_860_LOGOTOFF2", /* name */
416 true, /* partial_inplace */
417 0xffffffff, /* src_mask */
418 0xffffffff, /* dst_mask */
419 false), /* pcrel_offset */
421 HOWTO (R_860_LOGOTOFF3, /* type */
422 0, /* rightshift */
423 2, /* size (0 = byte, 1 = short, 2 = long) */
424 32, /* bitsize */
425 false, /* pc_relative */
426 0, /* bitpos */
427 complain_overflow_dont, /* complain_on_overflow */
428 bfd_elf_generic_reloc, /* special_function */
429 "R_860_LOGOTOFF3", /* name */
430 true, /* partial_inplace */
431 0xffffffff, /* src_mask */
432 0xffffffff, /* dst_mask */
433 false), /* pcrel_offset */
435 HOWTO (R_860_LOPC, /* type */
436 0, /* rightshift */
437 2, /* size (0 = byte, 1 = short, 2 = long) */
438 16, /* bitsize */
439 true, /* pc_relative */
440 0, /* bitpos */
441 complain_overflow_bitfield, /* complain_on_overflow */
442 bfd_elf_generic_reloc, /* special_function */
443 "R_860_LOPC", /* name */
444 false, /* partial_inplace */
445 0xffff, /* src_mask */
446 0xffff, /* dst_mask */
447 true), /* pcrel_offset */
449 HOWTO (R_860_HIGHADJ, /* type */
450 0, /* rightshift */
451 2, /* size (0 = byte, 1 = short, 2 = long) */
452 16, /* bitsize */
453 false, /* pc_relative */
454 0, /* bitpos */
455 complain_overflow_dont, /* complain_on_overflow */
456 bfd_elf_generic_reloc, /* special_function */
457 "R_860_HIGHADJ", /* name */
458 false, /* partial_inplace */
459 0xffff, /* src_mask */
460 0xffff, /* dst_mask */
461 false), /* pcrel_offset */
463 HOWTO (R_860_HAGOT, /* type */
464 0, /* rightshift */
465 2, /* size (0 = byte, 1 = short, 2 = long) */
466 16, /* bitsize */
467 false, /* pc_relative */
468 0, /* bitpos */
469 complain_overflow_dont, /* complain_on_overflow */
470 bfd_elf_generic_reloc, /* special_function */
471 "R_860_HAGOT", /* name */
472 false, /* partial_inplace */
473 0, /* src_mask */
474 0xffff, /* dst_mask */
475 true), /* pcrel_offset */
477 HOWTO (R_860_HAGOTOFF, /* type */
478 0, /* rightshift */
479 2, /* size (0 = byte, 1 = short, 2 = long) */
480 32, /* bitsize */
481 false, /* pc_relative */
482 0, /* bitpos */
483 complain_overflow_dont, /* complain_on_overflow */
484 bfd_elf_generic_reloc, /* special_function */
485 "R_860_HAGOTOFF", /* name */
486 true, /* partial_inplace */
487 0xffffffff, /* src_mask */
488 0xffffffff, /* dst_mask */
489 false), /* pcrel_offset */
491 HOWTO (R_860_HAPC, /* type */
492 0, /* rightshift */
493 2, /* size (0 = byte, 1 = short, 2 = long) */
494 16, /* bitsize */
495 true, /* pc_relative */
496 0, /* bitpos */
497 complain_overflow_bitfield, /* complain_on_overflow */
498 bfd_elf_generic_reloc, /* special_function */
499 "R_860_HAPC", /* name */
500 false, /* partial_inplace */
501 0xffff, /* src_mask */
502 0xffff, /* dst_mask */
503 true), /* pcrel_offset */
505 HOWTO (R_860_HIGH, /* type */
506 16, /* rightshift */
507 2, /* size (0 = byte, 1 = short, 2 = long) */
508 16, /* bitsize */
509 false, /* pc_relative */
510 0, /* bitpos */
511 complain_overflow_dont, /* complain_on_overflow */
512 bfd_elf_generic_reloc, /* special_function */
513 "R_860_HIGH", /* name */
514 false, /* partial_inplace */
515 0xffff, /* src_mask */
516 0xffff, /* dst_mask */
517 false), /* pcrel_offset */
519 HOWTO (R_860_HIGOT, /* type */
520 0, /* rightshift */
521 2, /* size (0 = byte, 1 = short, 2 = long) */
522 16, /* bitsize */
523 false, /* pc_relative */
524 0, /* bitpos */
525 complain_overflow_dont, /* complain_on_overflow */
526 bfd_elf_generic_reloc, /* special_function */
527 "R_860_HIGOT", /* name */
528 false, /* partial_inplace */
529 0, /* src_mask */
530 0xffff, /* dst_mask */
531 true), /* pcrel_offset */
533 HOWTO (R_860_HIGOTOFF, /* type */
534 0, /* rightshift */
535 2, /* size (0 = byte, 1 = short, 2 = long) */
536 32, /* bitsize */
537 false, /* pc_relative */
538 0, /* bitpos */
539 complain_overflow_dont, /* complain_on_overflow */
540 bfd_elf_generic_reloc, /* special_function */
541 "R_860_HIGOTOFF", /* name */
542 true, /* partial_inplace */
543 0xffffffff, /* src_mask */
544 0xffffffff, /* dst_mask */
545 false), /* pcrel_offset */
549 static unsigned char elf_code_to_howto_index[R_860_max + 1];
551 static reloc_howto_type *
552 lookup_howto (rtype)
553 unsigned int rtype;
555 static int initialized = 0;
556 int i;
557 int howto_tbl_size = (int) (sizeof (elf32_i860_howto_table)
558 / sizeof (elf32_i860_howto_table[0]));
560 if (! initialized)
562 initialized = 1;
563 memset (elf_code_to_howto_index, 0xff,
564 sizeof (elf_code_to_howto_index));
565 for (i = 0; i < howto_tbl_size; i++)
566 elf_code_to_howto_index[elf32_i860_howto_table[i].type] = i;
569 BFD_ASSERT (rtype <= R_860_max);
570 i = elf_code_to_howto_index[rtype];
571 if (i >= howto_tbl_size)
572 return 0;
573 return elf32_i860_howto_table + i;
577 /* Given a BFD reloc, return the matching HOWTO structure. */
578 static reloc_howto_type *
579 elf32_i860_reloc_type_lookup (abfd, code)
580 bfd * abfd ATTRIBUTE_UNUSED;
581 bfd_reloc_code_real_type code;
583 unsigned int rtype;
585 switch (code)
587 case BFD_RELOC_NONE:
588 rtype = R_860_NONE;
589 break;
590 case BFD_RELOC_32:
591 rtype = R_860_32;
592 break;
593 case BFD_RELOC_860_COPY:
594 rtype = R_860_COPY;
595 break;
596 case BFD_RELOC_860_GLOB_DAT:
597 rtype = R_860_GLOB_DAT;
598 break;
599 case BFD_RELOC_860_JUMP_SLOT:
600 rtype = R_860_JUMP_SLOT;
601 break;
602 case BFD_RELOC_860_RELATIVE:
603 rtype = R_860_RELATIVE;
604 break;
605 case BFD_RELOC_860_PC26:
606 rtype = R_860_PC26;
607 break;
608 case BFD_RELOC_860_PLT26:
609 rtype = R_860_PLT26;
610 break;
611 case BFD_RELOC_860_PC16:
612 rtype = R_860_PC16;
613 break;
614 case BFD_RELOC_860_LOW0:
615 rtype = R_860_LOW0;
616 break;
617 case BFD_RELOC_860_SPLIT0:
618 rtype = R_860_SPLIT0;
619 break;
620 case BFD_RELOC_860_LOW1:
621 rtype = R_860_LOW1;
622 break;
623 case BFD_RELOC_860_SPLIT1:
624 rtype = R_860_SPLIT1;
625 break;
626 case BFD_RELOC_860_LOW2:
627 rtype = R_860_LOW2;
628 break;
629 case BFD_RELOC_860_SPLIT2:
630 rtype = R_860_SPLIT2;
631 break;
632 case BFD_RELOC_860_LOW3:
633 rtype = R_860_LOW3;
634 break;
635 case BFD_RELOC_860_LOGOT0:
636 rtype = R_860_LOGOT0;
637 break;
638 case BFD_RELOC_860_SPGOT0:
639 rtype = R_860_SPGOT0;
640 break;
641 case BFD_RELOC_860_LOGOT1:
642 rtype = R_860_LOGOT1;
643 break;
644 case BFD_RELOC_860_SPGOT1:
645 rtype = R_860_SPGOT1;
646 break;
647 case BFD_RELOC_860_LOGOTOFF0:
648 rtype = R_860_LOGOTOFF0;
649 break;
650 case BFD_RELOC_860_SPGOTOFF0:
651 rtype = R_860_SPGOTOFF0;
652 break;
653 case BFD_RELOC_860_LOGOTOFF1:
654 rtype = R_860_LOGOTOFF1;
655 break;
656 case BFD_RELOC_860_SPGOTOFF1:
657 rtype = R_860_SPGOTOFF1;
658 break;
659 case BFD_RELOC_860_LOGOTOFF2:
660 rtype = R_860_LOGOTOFF2;
661 break;
662 case BFD_RELOC_860_LOGOTOFF3:
663 rtype = R_860_LOGOTOFF3;
664 break;
665 case BFD_RELOC_860_LOPC:
666 rtype = R_860_LOPC;
667 break;
668 case BFD_RELOC_860_HIGHADJ:
669 rtype = R_860_HIGHADJ;
670 break;
671 case BFD_RELOC_860_HAGOT:
672 rtype = R_860_HAGOT;
673 break;
674 case BFD_RELOC_860_HAGOTOFF:
675 rtype = R_860_HAGOTOFF;
676 break;
677 case BFD_RELOC_860_HAPC:
678 rtype = R_860_HAPC;
679 break;
680 case BFD_RELOC_860_HIGH:
681 rtype = R_860_HIGH;
682 break;
683 case BFD_RELOC_860_HIGOT:
684 rtype = R_860_HIGOT;
685 break;
686 case BFD_RELOC_860_HIGOTOFF:
687 rtype = R_860_HIGOTOFF;
688 break;
689 default:
690 rtype = 0;
691 break;
693 return lookup_howto (rtype);
697 /* Given a ELF reloc, return the matching HOWTO structure. */
698 static void
699 elf32_i860_info_to_howto_rela (abfd, bfd_reloc, elf_reloc)
700 bfd *abfd ATTRIBUTE_UNUSED;
701 arelent *bfd_reloc;
702 Elf64_Internal_Rela *elf_reloc;
704 bfd_reloc->howto = lookup_howto (ELF32_R_TYPE (elf_reloc->r_info));
709 /* Specialized relocation handler for R_860_SPLITn. These relocations
710 involves a 16-bit field that is split into two contiguous parts. */
711 static bfd_reloc_status_type
712 elf32_i860_relocate_splitn (input_bfd, rello, contents, value)
713 bfd *input_bfd;
714 Elf_Internal_Rela *rello;
715 bfd_byte *contents;
716 bfd_vma value;
718 bfd_vma insn;
719 reloc_howto_type *howto;
720 howto = lookup_howto (ELF32_R_TYPE (rello->r_info));
721 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
723 /* Relocate. */
724 value += rello->r_addend;
726 /* Separate the fields and insert. */
727 value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
728 insn = (insn & ~howto->dst_mask) | value;
730 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
731 return bfd_reloc_ok;
735 /* Specialized relocation handler for R_860_PC16. This relocation
736 involves a 16-bit, PC-relative field that is split into two contiguous
737 parts. */
738 static bfd_reloc_status_type
739 elf32_i860_relocate_pc16 (input_bfd, input_section, rello, contents, value)
740 bfd *input_bfd;
741 asection *input_section;
742 Elf_Internal_Rela *rello;
743 bfd_byte *contents;
744 bfd_vma value;
746 bfd_vma insn;
747 reloc_howto_type *howto;
748 howto = lookup_howto (ELF32_R_TYPE (rello->r_info));
749 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
751 /* Adjust for PC-relative relocation. */
752 value -= (input_section->output_section->vma
753 + input_section->output_offset);
754 value -= rello->r_offset;
756 /* Relocate. */
757 value += rello->r_addend;
759 /* Separate the fields and insert. */
760 value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
761 insn = (insn & ~howto->dst_mask) | value;
763 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
764 return bfd_reloc_ok;
769 /* Specialized relocation handler for R_860_PC26. This relocation
770 involves a 26-bit, PC-relative field which must be adjusted by 4. */
771 static bfd_reloc_status_type
772 elf32_i860_relocate_pc26 (input_bfd, input_section, rello, contents, value)
773 bfd *input_bfd;
774 asection *input_section;
775 Elf_Internal_Rela *rello;
776 bfd_byte *contents;
777 bfd_vma value;
779 bfd_vma insn;
780 reloc_howto_type *howto;
781 howto = lookup_howto (ELF32_R_TYPE (rello->r_info));
782 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
784 /* Adjust for PC-relative relocation. */
785 value -= (input_section->output_section->vma
786 + input_section->output_offset);
787 value -= rello->r_offset;
789 /* Relocate. */
790 value += rello->r_addend;
792 /* Adjust value by 4 and insert the field. */
793 value = ((value - 4) >> howto->rightshift) & howto->dst_mask;
794 insn = (insn & ~howto->dst_mask) | value;
796 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
797 return bfd_reloc_ok;
802 /* Specialized relocation handler for R_860_HIGHADJ. */
803 static bfd_reloc_status_type
804 elf32_i860_relocate_highadj (input_bfd, rel, contents, value)
805 bfd *input_bfd;
806 Elf_Internal_Rela *rel;
807 bfd_byte *contents;
808 bfd_vma value;
810 bfd_vma insn;
812 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
814 value += ((rel->r_addend & 0x8000) << 1);
815 value += rel->r_addend;
816 value = ((value >> 16) & 0xffff);
818 insn = (insn & 0xffff0000) | value;
820 bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
821 return bfd_reloc_ok;
825 /* Perform a single relocation. By default we use the standard BFD
826 routines. However, we handle some specially. */
827 static bfd_reloc_status_type
828 i860_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation)
829 reloc_howto_type * howto;
830 bfd * input_bfd;
831 asection * input_section;
832 bfd_byte * contents;
833 Elf_Internal_Rela * rel;
834 bfd_vma relocation;
836 return _bfd_final_link_relocate (howto, input_bfd, input_section,
837 contents, rel->r_offset, relocation,
838 rel->r_addend);
842 /* Relocate an i860 ELF section.
844 This is boiler-plate code copied from fr30.
845 There is some attempt to make this function usable for many architectures,
846 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
847 if only to serve as a learning tool.
849 The RELOCATE_SECTION function is called by the new ELF backend linker
850 to handle the relocations for a section.
852 The relocs are always passed as Rela structures; if the section
853 actually uses Rel structures, the r_addend field will always be
854 zero.
856 This function is responsible for adjusting the section contents as
857 necessary, and (if using Rela relocs and generating a relocateable
858 output file) adjusting the reloc addend as necessary.
860 This function does not have to worry about setting the reloc
861 address or the reloc symbol index.
863 LOCAL_SYMS is a pointer to the swapped in local symbols.
865 LOCAL_SECTIONS is an array giving the section in the input file
866 corresponding to the st_shndx field of each local symbol.
868 The global hash table entry for the global symbols can be found
869 via elf_sym_hashes (input_bfd).
871 When generating relocateable output, this function must handle
872 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
873 going to be the section symbol corresponding to the output
874 section, which means that the addend must be adjusted
875 accordingly. */
876 static boolean
877 elf32_i860_relocate_section (output_bfd, info, input_bfd, input_section,
878 contents, relocs, local_syms, local_sections)
879 bfd * output_bfd ATTRIBUTE_UNUSED;
880 struct bfd_link_info * info;
881 bfd * input_bfd;
882 asection * input_section;
883 bfd_byte * contents;
884 Elf_Internal_Rela * relocs;
885 Elf_Internal_Sym * local_syms;
886 asection ** local_sections;
888 Elf_Internal_Shdr * symtab_hdr;
889 struct elf_link_hash_entry ** sym_hashes;
890 Elf_Internal_Rela * rel;
891 Elf_Internal_Rela * relend;
893 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
894 sym_hashes = elf_sym_hashes (input_bfd);
895 relend = relocs + input_section->reloc_count;
897 for (rel = relocs; rel < relend; rel ++)
899 reloc_howto_type * howto;
900 unsigned long r_symndx;
901 Elf_Internal_Sym * sym;
902 asection * sec;
903 struct elf_link_hash_entry * h;
904 bfd_vma relocation;
905 bfd_reloc_status_type r;
906 const char * name = NULL;
907 int r_type;
909 r_type = ELF32_R_TYPE (rel->r_info);
911 #if 0
912 if ( r_type == R_860_GNU_VTINHERIT
913 || r_type == R_860_GNU_VTENTRY)
914 continue;
915 #endif
917 r_symndx = ELF32_R_SYM (rel->r_info);
919 if (info->relocateable)
921 /* This is a relocateable link. We don't have to change
922 anything, unless the reloc is against a section symbol,
923 in which case we have to adjust according to where the
924 section symbol winds up in the output section. */
925 if (r_symndx < symtab_hdr->sh_info)
927 sym = local_syms + r_symndx;
929 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
931 sec = local_sections [r_symndx];
932 rel->r_addend += sec->output_offset + sym->st_value;
936 continue;
939 /* This is a final link. */
940 howto = lookup_howto (ELF32_R_TYPE (rel->r_info));
941 h = NULL;
942 sym = NULL;
943 sec = NULL;
945 if (r_symndx < symtab_hdr->sh_info)
947 sym = local_syms + r_symndx;
948 sec = local_sections [r_symndx];
949 relocation = (sec->output_section->vma
950 + sec->output_offset
951 + sym->st_value);
953 name = bfd_elf_string_from_elf_section
954 (input_bfd, symtab_hdr->sh_link, sym->st_name);
955 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
957 else
959 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
961 while (h->root.type == bfd_link_hash_indirect
962 || h->root.type == bfd_link_hash_warning)
963 h = (struct elf_link_hash_entry *) h->root.u.i.link;
965 name = h->root.root.string;
967 if (h->root.type == bfd_link_hash_defined
968 || h->root.type == bfd_link_hash_defweak)
970 sec = h->root.u.def.section;
971 relocation = (h->root.u.def.value
972 + sec->output_section->vma
973 + sec->output_offset);
975 else if (h->root.type == bfd_link_hash_undefweak)
977 relocation = 0;
979 else
981 if (! ((*info->callbacks->undefined_symbol)
982 (info, h->root.root.string, input_bfd,
983 input_section, rel->r_offset, true)))
984 return false;
985 relocation = 0;
989 switch (r_type)
991 default:
992 r = i860_final_link_relocate (howto, input_bfd, input_section,
993 contents, rel, relocation);
994 break;
996 case R_860_HIGHADJ:
997 r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
998 relocation);
999 break;
1001 case R_860_PC16:
1002 r = elf32_i860_relocate_pc16 (input_bfd, input_section, rel,
1003 contents, relocation);
1004 break;
1006 case R_860_PC26:
1007 r = elf32_i860_relocate_pc26 (input_bfd, input_section, rel,
1008 contents, relocation);
1009 break;
1011 case R_860_SPLIT0:
1012 case R_860_SPLIT1:
1013 case R_860_SPLIT2:
1014 r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
1015 relocation);
1016 break;
1018 /* We do not yet handle GOT/PLT/Dynamic relocations. */
1019 case R_860_COPY:
1020 case R_860_GLOB_DAT:
1021 case R_860_JUMP_SLOT:
1022 case R_860_RELATIVE:
1023 case R_860_PLT26:
1024 case R_860_LOGOT0:
1025 case R_860_SPGOT0:
1026 case R_860_LOGOT1:
1027 case R_860_SPGOT1:
1028 case R_860_LOGOTOFF0:
1029 case R_860_SPGOTOFF0:
1030 case R_860_LOGOTOFF1:
1031 case R_860_SPGOTOFF1:
1032 case R_860_LOGOTOFF2:
1033 case R_860_LOGOTOFF3:
1034 case R_860_LOPC:
1035 case R_860_HAGOT:
1036 case R_860_HAGOTOFF:
1037 case R_860_HAPC:
1038 case R_860_HIGOT:
1039 case R_860_HIGOTOFF:
1040 r = bfd_reloc_notsupported;
1041 break;
1044 if (r != bfd_reloc_ok)
1046 const char * msg = (const char *) NULL;
1048 switch (r)
1050 case bfd_reloc_overflow:
1051 r = info->callbacks->reloc_overflow
1052 (info, name, howto->name, (bfd_vma) 0,
1053 input_bfd, input_section, rel->r_offset);
1054 break;
1056 case bfd_reloc_undefined:
1057 r = info->callbacks->undefined_symbol
1058 (info, name, input_bfd, input_section, rel->r_offset, true);
1059 break;
1061 case bfd_reloc_outofrange:
1062 msg = _("internal error: out of range error");
1063 break;
1065 case bfd_reloc_notsupported:
1066 msg = _("internal error: unsupported relocation error");
1067 break;
1069 case bfd_reloc_dangerous:
1070 msg = _("internal error: dangerous relocation");
1071 break;
1073 default:
1074 msg = _("internal error: unknown error");
1075 break;
1078 if (msg)
1079 r = info->callbacks->warning
1080 (info, msg, name, input_bfd, input_section, rel->r_offset);
1082 if (! r)
1083 return false;
1087 return true;
1091 /* Return whether a symbol name implies a local label. SVR4/860 compilers
1092 generate labels of the form ".ep.function_name" to denote the end of a
1093 function prolog. These should be local.
1094 ??? Do any other SVR4 compilers have this convention? If so, this should
1095 be added to the generic routine. */
1096 static boolean
1097 elf32_i860_is_local_label_name (abfd, name)
1098 bfd *abfd;
1099 const char *name;
1101 if (name[0] == '.' && name[1] == 'e' && name[2] == 'p' && name[3] == '.')
1102 return true;
1104 return _bfd_elf_is_local_label_name (abfd, name);
1109 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1110 #define TARGET_BIG_NAME "elf32-i860"
1111 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1112 #define TARGET_LITTLE_NAME "elf32-i860-little"
1113 #define ELF_ARCH bfd_arch_i860
1114 #define ELF_MACHINE_CODE EM_860
1115 #define ELF_MAXPAGESIZE 4096
1117 #define elf_info_to_howto_rel NULL
1118 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1119 #define elf_backend_relocate_section elf32_i860_relocate_section
1120 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1121 #define bfd_elf32_bfd_is_local_label_name elf32_i860_is_local_label_name
1123 #include "elf32-target.h"