2000-08-10 Jason Eckhardt <jle@cygnus.com>
[binutils-gdb.git] / bfd / elf32-i860.c
1 /* Intel i860 specific support for 32-bit ELF.
2 Copyright 1993, 2000 Free Software Foundation, Inc.
3
4 Full i860 support contributed by Jason Eckhardt <jle@cygnus.com>.
5
6 This file is part of BFD, the Binary File Descriptor library.
7
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.
12
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.
17
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. */
21
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/i860.h"
27
28
29 /* Prototypes. */
30 static reloc_howto_type *lookup_howto
31 PARAMS ((unsigned int));
32
33 static reloc_howto_type *elf32_i860_reloc_type_lookup
34 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
35
36 static void elf32_i860_info_to_howto_rela
37 PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
38
39 static bfd_reloc_status_type elf32_i860_relocate_splitn
40 PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
41
42 #if 0
43 static bfd_reloc_status_type elf32_i860_relocate_pc16
44 PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
45 #endif
46
47 static bfd_reloc_status_type elf32_i860_relocate_highadj
48 PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
49
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 **));
53
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));
57
58
59
60 /* This howto table is preliminary. */
61 static reloc_howto_type elf32_i860_howto_table [] =
62 {
63 /* This relocation does nothing. */
64 HOWTO (R_860_NONE, /* type */
65 0, /* rightshift */
66 2, /* size (0 = byte, 1 = short, 2 = long) */
67 32, /* bitsize */
68 false, /* pc_relative */
69 0, /* bitpos */
70 complain_overflow_bitfield, /* complain_on_overflow */
71 bfd_elf_generic_reloc, /* special_function */
72 "R_860_NONE", /* name */
73 false, /* partial_inplace */
74 0, /* src_mask */
75 0, /* dst_mask */
76 false), /* pcrel_offset */
77
78 /* A 32-bit absolute relocation. */
79 HOWTO (R_860_32, /* type */
80 0, /* rightshift */
81 2, /* size (0 = byte, 1 = short, 2 = long) */
82 32, /* bitsize */
83 false, /* pc_relative */
84 0, /* bitpos */
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 */
92
93 HOWTO (R_860_COPY, /* type */
94 0, /* rightshift */
95 2, /* size (0 = byte, 1 = short, 2 = long) */
96 32, /* bitsize */
97 false, /* pc_relative */
98 0, /* bitpos */
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 */
106
107 HOWTO (R_860_GLOB_DAT, /* type */
108 0, /* rightshift */
109 2, /* size (0 = byte, 1 = short, 2 = long) */
110 32, /* bitsize */
111 false, /* pc_relative */
112 0, /* bitpos */
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 */
120
121 HOWTO (R_860_JUMP_SLOT, /* type */
122 0, /* rightshift */
123 2, /* size (0 = byte, 1 = short, 2 = long) */
124 32, /* bitsize */
125 false, /* pc_relative */
126 0, /* bitpos */
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 */
134
135 HOWTO (R_860_RELATIVE, /* type */
136 0, /* rightshift */
137 2, /* size (0 = byte, 1 = short, 2 = long) */
138 32, /* bitsize */
139 false, /* pc_relative */
140 0, /* bitpos */
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 */
148
149 /* A 26-bit PC-relative relocation. */
150 HOWTO (R_860_PC26, /* type */
151 2, /* rightshift */
152 2, /* size (0 = byte, 1 = short, 2 = long) */
153 26, /* bitsize */
154 true, /* pc_relative */
155 0, /* bitpos */
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 */
163
164 HOWTO (R_860_PLT26, /* type */
165 0, /* rightshift */
166 2, /* size (0 = byte, 1 = short, 2 = long) */
167 26, /* bitsize */
168 true, /* pc_relative */
169 0, /* bitpos */
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 */
177
178 /* A 16-bit PC-relative relocation. */
179 HOWTO (R_860_PC16, /* type */
180 2, /* rightshift */
181 2, /* size (0 = byte, 1 = short, 2 = long) */
182 16, /* bitsize */
183 true, /* pc_relative */
184 0, /* bitpos */
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 */
192
193 HOWTO (R_860_LOW0, /* type */
194 0, /* rightshift */
195 2, /* size (0 = byte, 1 = short, 2 = long) */
196 16, /* bitsize */
197 false, /* pc_relative */
198 0, /* bitpos */
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 */
206
207 HOWTO (R_860_SPLIT0, /* type */
208 0, /* rightshift */
209 2, /* size (0 = byte, 1 = short, 2 = long) */
210 16, /* bitsize */
211 false, /* pc_relative */
212 0, /* bitpos */
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 */
220
221 HOWTO (R_860_LOW1, /* type */
222 0, /* rightshift */
223 2, /* size (0 = byte, 1 = short, 2 = long) */
224 16, /* bitsize */
225 false, /* pc_relative */
226 0, /* bitpos */
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 */
234
235 HOWTO (R_860_SPLIT1, /* type */
236 0, /* rightshift */
237 2, /* size (0 = byte, 1 = short, 2 = long) */
238 16, /* bitsize */
239 false, /* pc_relative */
240 0, /* bitpos */
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 */
248
249 HOWTO (R_860_LOW2, /* type */
250 0, /* rightshift */
251 2, /* size (0 = byte, 1 = short, 2 = long) */
252 16, /* bitsize */
253 false, /* pc_relative */
254 0, /* bitpos */
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 */
262
263 HOWTO (R_860_SPLIT2, /* type */
264 0, /* rightshift */
265 2, /* size (0 = byte, 1 = short, 2 = long) */
266 16, /* bitsize */
267 false, /* pc_relative */
268 0, /* bitpos */
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 */
276
277 HOWTO (R_860_LOW3, /* type */
278 0, /* rightshift */
279 2, /* size (0 = byte, 1 = short, 2 = long) */
280 16, /* bitsize */
281 false, /* pc_relative */
282 0, /* bitpos */
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 */
290
291 HOWTO (R_860_LOGOT0, /* type */
292 0, /* rightshift */
293 2, /* size (0 = byte, 1 = short, 2 = long) */
294 16, /* bitsize */
295 false, /* pc_relative */
296 0, /* bitpos */
297 complain_overflow_dont, /* complain_on_overflow */
298 bfd_elf_generic_reloc, /* special_function */
299 "R_860_LOGOT0", /* name */
300 false, /* partial_inplace */
301 0, /* src_mask */
302 0xffff, /* dst_mask */
303 true), /* pcrel_offset */
304
305 HOWTO (R_860_SPGOT0, /* type */
306 0, /* rightshift */
307 2, /* size (0 = byte, 1 = short, 2 = long) */
308 16, /* bitsize */
309 false, /* pc_relative */
310 0, /* bitpos */
311 complain_overflow_dont, /* complain_on_overflow */
312 bfd_elf_generic_reloc, /* special_function */
313 "R_860_SPGOT0", /* name */
314 false, /* partial_inplace */
315 0, /* src_mask */
316 0xffff, /* dst_mask */
317 true), /* pcrel_offset */
318
319 HOWTO (R_860_LOGOT1, /* type */
320 0, /* rightshift */
321 2, /* size (0 = byte, 1 = short, 2 = long) */
322 16, /* bitsize */
323 false, /* pc_relative */
324 0, /* bitpos */
325 complain_overflow_dont, /* complain_on_overflow */
326 bfd_elf_generic_reloc, /* special_function */
327 "R_860_LOGOT1", /* name */
328 false, /* partial_inplace */
329 0, /* src_mask */
330 0xffff, /* dst_mask */
331 true), /* pcrel_offset */
332
333 HOWTO (R_860_SPGOT1, /* type */
334 0, /* rightshift */
335 2, /* size (0 = byte, 1 = short, 2 = long) */
336 16, /* bitsize */
337 false, /* pc_relative */
338 0, /* bitpos */
339 complain_overflow_dont, /* complain_on_overflow */
340 bfd_elf_generic_reloc, /* special_function */
341 "R_860_SPGOT1", /* name */
342 false, /* partial_inplace */
343 0, /* src_mask */
344 0xffff, /* dst_mask */
345 true), /* pcrel_offset */
346
347 HOWTO (R_860_LOGOTOFF0, /* type */
348 0, /* rightshift */
349 2, /* size (0 = byte, 1 = short, 2 = long) */
350 32, /* bitsize */
351 false, /* pc_relative */
352 0, /* bitpos */
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 */
360
361 HOWTO (R_860_SPGOTOFF0, /* type */
362 0, /* rightshift */
363 2, /* size (0 = byte, 1 = short, 2 = long) */
364 32, /* bitsize */
365 false, /* pc_relative */
366 0, /* bitpos */
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 */
374
375 HOWTO (R_860_LOGOTOFF1, /* type */
376 0, /* rightshift */
377 2, /* size (0 = byte, 1 = short, 2 = long) */
378 32, /* bitsize */
379 false, /* pc_relative */
380 0, /* bitpos */
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 */
388
389 HOWTO (R_860_SPGOTOFF1, /* type */
390 0, /* rightshift */
391 2, /* size (0 = byte, 1 = short, 2 = long) */
392 32, /* bitsize */
393 false, /* pc_relative */
394 0, /* bitpos */
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 */
402
403 HOWTO (R_860_LOGOTOFF2, /* type */
404 0, /* rightshift */
405 2, /* size (0 = byte, 1 = short, 2 = long) */
406 32, /* bitsize */
407 false, /* pc_relative */
408 0, /* bitpos */
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 */
416
417 HOWTO (R_860_LOGOTOFF3, /* type */
418 0, /* rightshift */
419 2, /* size (0 = byte, 1 = short, 2 = long) */
420 32, /* bitsize */
421 false, /* pc_relative */
422 0, /* bitpos */
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 */
430
431 HOWTO (R_860_LOPC, /* type */
432 0, /* rightshift */
433 2, /* size (0 = byte, 1 = short, 2 = long) */
434 16, /* bitsize */
435 true, /* pc_relative */
436 0, /* bitpos */
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 */
444
445 HOWTO (R_860_HIGHADJ, /* type */
446 0, /* rightshift */
447 2, /* size (0 = byte, 1 = short, 2 = long) */
448 16, /* bitsize */
449 false, /* pc_relative */
450 0, /* bitpos */
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 */
458
459 HOWTO (R_860_HAGOT, /* type */
460 0, /* rightshift */
461 2, /* size (0 = byte, 1 = short, 2 = long) */
462 16, /* bitsize */
463 false, /* pc_relative */
464 0, /* bitpos */
465 complain_overflow_dont, /* complain_on_overflow */
466 bfd_elf_generic_reloc, /* special_function */
467 "R_860_HAGOT", /* name */
468 false, /* partial_inplace */
469 0, /* src_mask */
470 0xffff, /* dst_mask */
471 true), /* pcrel_offset */
472
473 HOWTO (R_860_HAGOTOFF, /* type */
474 0, /* rightshift */
475 2, /* size (0 = byte, 1 = short, 2 = long) */
476 32, /* bitsize */
477 false, /* pc_relative */
478 0, /* bitpos */
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 */
486
487 HOWTO (R_860_HAPC, /* type */
488 0, /* rightshift */
489 2, /* size (0 = byte, 1 = short, 2 = long) */
490 16, /* bitsize */
491 true, /* pc_relative */
492 0, /* bitpos */
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 */
500
501 HOWTO (R_860_HIGH, /* type */
502 16, /* rightshift */
503 2, /* size (0 = byte, 1 = short, 2 = long) */
504 16, /* bitsize */
505 false, /* pc_relative */
506 0, /* bitpos */
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 */
514
515 HOWTO (R_860_HIGOT, /* type */
516 0, /* rightshift */
517 2, /* size (0 = byte, 1 = short, 2 = long) */
518 16, /* bitsize */
519 false, /* pc_relative */
520 0, /* bitpos */
521 complain_overflow_dont, /* complain_on_overflow */
522 bfd_elf_generic_reloc, /* special_function */
523 "R_860_HIGOT", /* name */
524 false, /* partial_inplace */
525 0, /* src_mask */
526 0xffff, /* dst_mask */
527 true), /* pcrel_offset */
528
529 HOWTO (R_860_HIGOTOFF, /* type */
530 0, /* rightshift */
531 2, /* size (0 = byte, 1 = short, 2 = long) */
532 32, /* bitsize */
533 false, /* pc_relative */
534 0, /* bitpos */
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 */
542 };
543
544 \f
545 static unsigned char elf_code_to_howto_index[R_860_max + 1];
546
547 static reloc_howto_type *
548 lookup_howto (rtype)
549 unsigned int rtype;
550 {
551 static int initialized = 0;
552 int i;
553 int howto_tbl_size = (int) (sizeof (elf32_i860_howto_table)
554 / sizeof (elf32_i860_howto_table[0]));
555
556 if (! initialized)
557 {
558 initialized = 1;
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;
563 }
564
565 BFD_ASSERT (rtype <= R_860_max);
566 i = elf_code_to_howto_index[rtype];
567 if (i >= howto_tbl_size)
568 return 0;
569 return elf32_i860_howto_table + i;
570 }
571
572
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;
578 {
579 unsigned int rtype;
580
581 switch (code)
582 {
583 case BFD_RELOC_NONE:
584 rtype = R_860_NONE;
585 break;
586 case BFD_RELOC_32:
587 rtype = R_860_32;
588 break;
589 case BFD_RELOC_860_COPY:
590 rtype = R_860_COPY;
591 break;
592 case BFD_RELOC_860_GLOB_DAT:
593 rtype = R_860_GLOB_DAT;
594 break;
595 case BFD_RELOC_860_JUMP_SLOT:
596 rtype = R_860_JUMP_SLOT;
597 break;
598 case BFD_RELOC_860_RELATIVE:
599 rtype = R_860_RELATIVE;
600 break;
601 case BFD_RELOC_860_PC26:
602 rtype = R_860_PC26;
603 break;
604 case BFD_RELOC_860_PLT26:
605 rtype = R_860_PLT26;
606 break;
607 case BFD_RELOC_860_PC16:
608 rtype = R_860_PC16;
609 break;
610 case BFD_RELOC_860_LOW0:
611 rtype = R_860_LOW0;
612 break;
613 case BFD_RELOC_860_SPLIT0:
614 rtype = R_860_SPLIT0;
615 break;
616 case BFD_RELOC_860_LOW1:
617 rtype = R_860_LOW1;
618 break;
619 case BFD_RELOC_860_SPLIT1:
620 rtype = R_860_SPLIT1;
621 break;
622 case BFD_RELOC_860_LOW2:
623 rtype = R_860_LOW2;
624 break;
625 case BFD_RELOC_860_SPLIT2:
626 rtype = R_860_SPLIT2;
627 break;
628 case BFD_RELOC_860_LOW3:
629 rtype = R_860_LOW3;
630 break;
631 case BFD_RELOC_860_LOGOT0:
632 rtype = R_860_LOGOT0;
633 break;
634 case BFD_RELOC_860_SPGOT0:
635 rtype = R_860_SPGOT0;
636 break;
637 case BFD_RELOC_860_LOGOT1:
638 rtype = R_860_LOGOT1;
639 break;
640 case BFD_RELOC_860_SPGOT1:
641 rtype = R_860_SPGOT1;
642 break;
643 case BFD_RELOC_860_LOGOTOFF0:
644 rtype = R_860_LOGOTOFF0;
645 break;
646 case BFD_RELOC_860_SPGOTOFF0:
647 rtype = R_860_SPGOTOFF0;
648 break;
649 case BFD_RELOC_860_LOGOTOFF1:
650 rtype = R_860_LOGOTOFF1;
651 break;
652 case BFD_RELOC_860_SPGOTOFF1:
653 rtype = R_860_SPGOTOFF1;
654 break;
655 case BFD_RELOC_860_LOGOTOFF2:
656 rtype = R_860_LOGOTOFF2;
657 break;
658 case BFD_RELOC_860_LOGOTOFF3:
659 rtype = R_860_LOGOTOFF3;
660 break;
661 case BFD_RELOC_860_LOPC:
662 rtype = R_860_LOPC;
663 break;
664 case BFD_RELOC_860_HIGHADJ:
665 rtype = R_860_HIGHADJ;
666 break;
667 case BFD_RELOC_860_HAGOT:
668 rtype = R_860_HAGOT;
669 break;
670 case BFD_RELOC_860_HAGOTOFF:
671 rtype = R_860_HAGOTOFF;
672 break;
673 case BFD_RELOC_860_HAPC:
674 rtype = R_860_HAPC;
675 break;
676 case BFD_RELOC_860_HIGH:
677 rtype = R_860_HIGH;
678 break;
679 case BFD_RELOC_860_HIGOT:
680 rtype = R_860_HIGOT;
681 break;
682 case BFD_RELOC_860_HIGOTOFF:
683 rtype = R_860_HIGOTOFF;
684 break;
685 default:
686 rtype = 0;
687 break;
688 }
689 return lookup_howto (rtype);
690 }
691
692
693 /* Given a ELF reloc, return the matching HOWTO structure. */
694 static void
695 elf32_i860_info_to_howto_rela (abfd, bfd_reloc, elf_reloc)
696 bfd *abfd ATTRIBUTE_UNUSED;
697 arelent *bfd_reloc;
698 Elf64_Internal_Rela *elf_reloc;
699 {
700 bfd_reloc->howto = lookup_howto (ELF32_R_TYPE (elf_reloc->r_info));
701 }
702
703
704 \f
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)
709 bfd *input_bfd;
710 Elf_Internal_Rela *rello;
711 bfd_byte *contents;
712 bfd_vma value;
713 {
714 bfd_vma insn, t;
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);
718
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);
723
724 /* Relocate. */
725 value += (rello->r_addend + t);
726
727 /* Separate the fields and re-insert. */
728 value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
729 insn = (insn & ~howto->dst_mask) | value;
730
731 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
732 return bfd_reloc_ok;
733 }
734
735
736 #if 0
737 /* Specialized relocation handler for R_860_PC16. This relocation
738 involves a 16-bit, PC-relative field that is split into two contiguous
739 parts. */
740 static bfd_reloc_status_type
741 elf32_i860_relocate_pc16 (input_bfd, rello, contents, value)
742 bfd *input_bfd;
743 Elf_Internal_Rela *rello;
744 bfd_byte *contents;
745 bfd_vma value;
746 {
747 }
748 #endif
749
750
751 /* Specialized relocation handler for R_860_HIGHADJ. */
752 static bfd_reloc_status_type
753 elf32_i860_relocate_highadj (input_bfd, rel, contents, value)
754 bfd *input_bfd;
755 Elf_Internal_Rela *rel;
756 bfd_byte *contents;
757 bfd_vma value;
758 {
759 bfd_vma insn;
760
761 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
762
763 value += ((rel->r_addend & 0x8000) << 1);
764 value += rel->r_addend;
765 value = ((value >> 16) & 0xffff);
766 value = (value + (insn & 0xffff)) & 0xffff;
767
768 insn = (insn & 0xffff0000) | value;
769
770 bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
771 return bfd_reloc_ok;
772 }
773
774
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;
780 bfd * input_bfd;
781 asection * input_section;
782 bfd_byte * contents;
783 Elf_Internal_Rela * rel;
784 bfd_vma relocation;
785 {
786 return _bfd_final_link_relocate (howto, input_bfd, input_section,
787 contents, rel->r_offset, relocation,
788 rel->r_addend);
789 }
790
791
792 /* Relocate an i860 ELF section.
793
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.
798
799 The RELOCATE_SECTION function is called by the new ELF backend linker
800 to handle the relocations for a section.
801
802 The relocs are always passed as Rela structures; if the section
803 actually uses Rel structures, the r_addend field will always be
804 zero.
805
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.
809
810 This function does not have to worry about setting the reloc
811 address or the reloc symbol index.
812
813 LOCAL_SYMS is a pointer to the swapped in local symbols.
814
815 LOCAL_SECTIONS is an array giving the section in the input file
816 corresponding to the st_shndx field of each local symbol.
817
818 The global hash table entry for the global symbols can be found
819 via elf_sym_hashes (input_bfd).
820
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
825 accordingly. */
826 static boolean
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;
831 bfd * input_bfd;
832 asection * input_section;
833 bfd_byte * contents;
834 Elf_Internal_Rela * relocs;
835 Elf_Internal_Sym * local_syms;
836 asection ** local_sections;
837 {
838 Elf_Internal_Shdr * symtab_hdr;
839 struct elf_link_hash_entry ** sym_hashes;
840 Elf_Internal_Rela * rel;
841 Elf_Internal_Rela * relend;
842
843 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
844 sym_hashes = elf_sym_hashes (input_bfd);
845 relend = relocs + input_section->reloc_count;
846
847 for (rel = relocs; rel < relend; rel ++)
848 {
849 reloc_howto_type * howto;
850 unsigned long r_symndx;
851 Elf_Internal_Sym * sym;
852 asection * sec;
853 struct elf_link_hash_entry * h;
854 bfd_vma relocation;
855 bfd_reloc_status_type r;
856 const char * name = NULL;
857 int r_type;
858
859 r_type = ELF32_R_TYPE (rel->r_info);
860
861 #if 0
862 if ( r_type == R_860_GNU_VTINHERIT
863 || r_type == R_860_GNU_VTENTRY)
864 continue;
865 #endif
866
867 r_symndx = ELF32_R_SYM (rel->r_info);
868
869 if (info->relocateable)
870 {
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)
876 {
877 sym = local_syms + r_symndx;
878
879 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
880 {
881 sec = local_sections [r_symndx];
882 rel->r_addend += sec->output_offset + sym->st_value;
883 }
884 }
885
886 continue;
887 }
888
889 /* This is a final link. */
890 howto = lookup_howto (ELF32_R_TYPE (rel->r_info));
891 h = NULL;
892 sym = NULL;
893 sec = NULL;
894
895 if (r_symndx < symtab_hdr->sh_info)
896 {
897 sym = local_syms + r_symndx;
898 sec = local_sections [r_symndx];
899 relocation = (sec->output_section->vma
900 + sec->output_offset
901 + sym->st_value);
902
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;
906 }
907 else
908 {
909 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
910
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;
914
915 name = h->root.root.string;
916
917 if (h->root.type == bfd_link_hash_defined
918 || h->root.type == bfd_link_hash_defweak)
919 {
920 sec = h->root.u.def.section;
921 relocation = (h->root.u.def.value
922 + sec->output_section->vma
923 + sec->output_offset);
924 }
925 else if (h->root.type == bfd_link_hash_undefweak)
926 {
927 relocation = 0;
928 }
929 else
930 {
931 if (! ((*info->callbacks->undefined_symbol)
932 (info, h->root.root.string, input_bfd,
933 input_section, rel->r_offset, true)))
934 return false;
935 relocation = 0;
936 }
937 }
938
939 switch (r_type)
940 {
941 default:
942 r = i860_final_link_relocate (howto, input_bfd, input_section,
943 contents, rel, relocation);
944 break;
945
946 case R_860_HIGHADJ:
947 r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
948 relocation);
949 break;
950
951 #if 0
952 case R_860_PC16:
953 r = elf32_i860_relocate_pc16 (input_bfd, rel, contents,
954 relocation);
955 break;
956 #endif
957
958 case R_860_SPLIT0:
959 case R_860_SPLIT1:
960 case R_860_SPLIT2:
961 r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
962 relocation);
963 break;
964
965 /* We do not yet handle GOT/PLT/Dynamic relocations. */
966 case R_860_COPY:
967 case R_860_GLOB_DAT:
968 case R_860_JUMP_SLOT:
969 case R_860_RELATIVE:
970 case R_860_PLT26:
971 case R_860_LOGOT0:
972 case R_860_SPGOT0:
973 case R_860_LOGOT1:
974 case R_860_SPGOT1:
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:
981 case R_860_LOPC:
982 case R_860_HAGOT:
983 case R_860_HAGOTOFF:
984 case R_860_HAPC:
985 case R_860_HIGOT:
986 case R_860_HIGOTOFF:
987 r = bfd_reloc_notsupported;
988 break;
989 }
990
991 if (r != bfd_reloc_ok)
992 {
993 const char * msg = (const char *) NULL;
994
995 switch (r)
996 {
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);
1001 break;
1002
1003 case bfd_reloc_undefined:
1004 r = info->callbacks->undefined_symbol
1005 (info, name, input_bfd, input_section, rel->r_offset, true);
1006 break;
1007
1008 case bfd_reloc_outofrange:
1009 msg = _("internal error: out of range error");
1010 break;
1011
1012 case bfd_reloc_notsupported:
1013 msg = _("internal error: unsupported relocation error");
1014 break;
1015
1016 case bfd_reloc_dangerous:
1017 msg = _("internal error: dangerous relocation");
1018 break;
1019
1020 default:
1021 msg = _("internal error: unknown error");
1022 break;
1023 }
1024
1025 if (msg)
1026 r = info->callbacks->warning
1027 (info, msg, name, input_bfd, input_section, rel->r_offset);
1028
1029 if (! r)
1030 return false;
1031 }
1032 }
1033
1034 return true;
1035 }
1036
1037
1038 \f
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
1046
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
1051
1052 #include "elf32-target.h"