* frame.c (put_frame_register): Don't use temporary buffer.
[deliverable/binutils-gdb.git] / bfd / elf32-i860.c
1 /* Intel i860 specific support for 32-bit ELF.
2 Copyright 1993, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008,
3 2010, 2011, 2012
4 Free Software Foundation, Inc.
5
6 Full i860 support contributed by Jason Eckhardt <jle@cygnus.com>.
7
8 This file is part of BFD, the Binary File Descriptor library.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
24
25 #include "sysdep.h"
26 #include "bfd.h"
27 #include "libbfd.h"
28 #include "elf-bfd.h"
29 #include "elf/i860.h"
30
31 /* special_function for R_860_PC26 relocation. */
32 static bfd_reloc_status_type
33 i860_howto_pc26_reloc (bfd *abfd ATTRIBUTE_UNUSED,
34 arelent *reloc_entry,
35 asymbol *symbol,
36 void *data ATTRIBUTE_UNUSED,
37 asection *input_section,
38 bfd *output_bfd,
39 char **error_message ATTRIBUTE_UNUSED)
40 {
41 bfd_vma insn;
42 bfd_vma relocation;
43 bfd_byte *addr;
44
45 if (output_bfd != NULL
46 && (symbol->flags & BSF_SECTION_SYM) == 0
47 && (! reloc_entry->howto->partial_inplace
48 || reloc_entry->addend == 0))
49 {
50 reloc_entry->address += input_section->output_offset;
51 return bfd_reloc_ok;
52 }
53
54 /* Used elf32-mips.c as an example. */
55 if (bfd_is_und_section (symbol->section)
56 && output_bfd == (bfd *) NULL)
57 return bfd_reloc_undefined;
58
59 if (bfd_is_com_section (symbol->section))
60 relocation = 0;
61 else
62 relocation = symbol->value;
63
64 relocation += symbol->section->output_section->vma;
65 relocation += symbol->section->output_offset;
66 relocation += reloc_entry->addend;
67
68 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
69 return bfd_reloc_outofrange;
70
71 /* Adjust for PC-relative relocation. */
72 relocation -= (input_section->output_section->vma
73 + input_section->output_offset
74 + reloc_entry->address
75 + 4);
76
77 /* Check for target out of range. */
78 if ((bfd_signed_vma)relocation > (0x3ffffff << 2)
79 || (bfd_signed_vma)relocation < (-0x4000000 << 2))
80 return bfd_reloc_outofrange;
81
82 addr = (bfd_byte *) data + reloc_entry->address;
83 insn = bfd_get_32 (abfd, addr);
84
85 relocation >>= reloc_entry->howto->rightshift;
86 insn = (insn & ~reloc_entry->howto->dst_mask)
87 | (relocation & reloc_entry->howto->dst_mask);
88
89 bfd_put_32 (abfd, (bfd_vma) insn, addr);
90
91 return bfd_reloc_ok;
92 }
93
94 /* special_function for R_860_PC16 relocation. */
95 static bfd_reloc_status_type
96 i860_howto_pc16_reloc (bfd *abfd,
97 arelent *reloc_entry,
98 asymbol *symbol,
99 void *data,
100 asection *input_section,
101 bfd *output_bfd,
102 char **error_message ATTRIBUTE_UNUSED)
103 {
104 bfd_vma insn;
105 bfd_vma relocation;
106 bfd_byte *addr;
107
108 if (output_bfd != NULL
109 && (symbol->flags & BSF_SECTION_SYM) == 0
110 && (! reloc_entry->howto->partial_inplace
111 || reloc_entry->addend == 0))
112 {
113 reloc_entry->address += input_section->output_offset;
114 return bfd_reloc_ok;
115 }
116
117 /* Used elf32-mips.c as an example. */
118 if (bfd_is_und_section (symbol->section)
119 && output_bfd == (bfd *) NULL)
120 return bfd_reloc_undefined;
121
122 if (bfd_is_com_section (symbol->section))
123 relocation = 0;
124 else
125 relocation = symbol->value;
126
127 relocation += symbol->section->output_section->vma;
128 relocation += symbol->section->output_offset;
129 relocation += reloc_entry->addend;
130
131 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
132 return bfd_reloc_outofrange;
133
134 /* Adjust for PC-relative relocation. */
135 relocation -= (input_section->output_section->vma
136 + input_section->output_offset
137 + reloc_entry->address
138 + 4);
139
140 /* Check for target out of range. */
141 if ((bfd_signed_vma)relocation > (0x7fff << 2)
142 || (bfd_signed_vma)relocation < (-0x8000 << 2))
143 return bfd_reloc_outofrange;
144
145 addr = (bfd_byte *) data + reloc_entry->address;
146 insn = bfd_get_32 (abfd, addr);
147
148 relocation >>= reloc_entry->howto->rightshift;
149 relocation = (((relocation & 0xf800) << 5) | (relocation & 0x7ff))
150 & reloc_entry->howto->dst_mask;
151 insn = (insn & ~reloc_entry->howto->dst_mask) | relocation;
152
153 bfd_put_32 (abfd, (bfd_vma) insn, addr);
154
155 return bfd_reloc_ok;
156 }
157
158 /* special_function for R_860_HIGHADJ relocation. */
159 static bfd_reloc_status_type
160 i860_howto_highadj_reloc (bfd *abfd,
161 arelent *reloc_entry,
162 asymbol *symbol,
163 void *data,
164 asection *input_section,
165 bfd *output_bfd,
166 char **error_message ATTRIBUTE_UNUSED)
167 {
168 bfd_vma insn;
169 bfd_vma relocation;
170 bfd_byte *addr;
171
172 if (output_bfd != NULL
173 && (symbol->flags & BSF_SECTION_SYM) == 0
174 && (! reloc_entry->howto->partial_inplace
175 || reloc_entry->addend == 0))
176 {
177 reloc_entry->address += input_section->output_offset;
178 return bfd_reloc_ok;
179 }
180
181 /* Used elf32-mips.c as an example. */
182 if (bfd_is_und_section (symbol->section)
183 && output_bfd == (bfd *) NULL)
184 return bfd_reloc_undefined;
185
186 if (bfd_is_com_section (symbol->section))
187 relocation = 0;
188 else
189 relocation = symbol->value;
190
191 relocation += symbol->section->output_section->vma;
192 relocation += symbol->section->output_offset;
193 relocation += reloc_entry->addend;
194 relocation += 0x8000;
195
196 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
197 return bfd_reloc_outofrange;
198
199 addr = (bfd_byte *) data + reloc_entry->address;
200 insn = bfd_get_32 (abfd, addr);
201
202 relocation = ((relocation >> 16) & 0xffff);
203
204 insn = (insn & 0xffff0000) | relocation;
205
206 bfd_put_32 (abfd, (bfd_vma) insn, addr);
207
208 return bfd_reloc_ok;
209 }
210
211 /* special_function for R_860_SPLITn relocations. */
212 static bfd_reloc_status_type
213 i860_howto_splitn_reloc (bfd *abfd,
214 arelent *reloc_entry,
215 asymbol *symbol,
216 void *data,
217 asection *input_section,
218 bfd *output_bfd,
219 char **error_message ATTRIBUTE_UNUSED)
220 {
221 bfd_vma insn;
222 bfd_vma relocation;
223 bfd_byte *addr;
224
225 if (output_bfd != NULL
226 && (symbol->flags & BSF_SECTION_SYM) == 0
227 && (! reloc_entry->howto->partial_inplace
228 || reloc_entry->addend == 0))
229 {
230 reloc_entry->address += input_section->output_offset;
231 return bfd_reloc_ok;
232 }
233
234 /* Used elf32-mips.c as an example. */
235 if (bfd_is_und_section (symbol->section)
236 && output_bfd == (bfd *) NULL)
237 return bfd_reloc_undefined;
238
239 if (bfd_is_com_section (symbol->section))
240 relocation = 0;
241 else
242 relocation = symbol->value;
243
244 relocation += symbol->section->output_section->vma;
245 relocation += symbol->section->output_offset;
246 relocation += reloc_entry->addend;
247
248 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
249 return bfd_reloc_outofrange;
250
251 addr = (bfd_byte *) data + reloc_entry->address;
252 insn = bfd_get_32 (abfd, addr);
253
254 relocation = (((relocation & 0xf800) << 5) | (relocation & 0x7ff))
255 & reloc_entry->howto->dst_mask;
256 insn = (insn & ~reloc_entry->howto->dst_mask) | relocation;
257
258 bfd_put_32 (abfd, (bfd_vma) insn, addr);
259
260 return bfd_reloc_ok;
261 }
262
263 /* This howto table is preliminary. */
264 static reloc_howto_type elf32_i860_howto_table [] =
265 {
266 /* This relocation does nothing. */
267 HOWTO (R_860_NONE, /* type */
268 0, /* rightshift */
269 2, /* size (0 = byte, 1 = short, 2 = long) */
270 32, /* bitsize */
271 FALSE, /* pc_relative */
272 0, /* bitpos */
273 complain_overflow_bitfield, /* complain_on_overflow */
274 bfd_elf_generic_reloc, /* special_function */
275 "R_860_NONE", /* name */
276 FALSE, /* partial_inplace */
277 0, /* src_mask */
278 0, /* dst_mask */
279 FALSE), /* pcrel_offset */
280
281 /* A 32-bit absolute relocation. */
282 HOWTO (R_860_32, /* type */
283 0, /* rightshift */
284 2, /* size (0 = byte, 1 = short, 2 = long) */
285 32, /* bitsize */
286 FALSE, /* pc_relative */
287 0, /* bitpos */
288 complain_overflow_bitfield, /* complain_on_overflow */
289 bfd_elf_generic_reloc, /* special_function */
290 "R_860_32", /* name */
291 FALSE, /* partial_inplace */
292 0xffffffff, /* src_mask */
293 0xffffffff, /* dst_mask */
294 FALSE), /* pcrel_offset */
295
296 HOWTO (R_860_COPY, /* type */
297 0, /* rightshift */
298 2, /* size (0 = byte, 1 = short, 2 = long) */
299 32, /* bitsize */
300 FALSE, /* pc_relative */
301 0, /* bitpos */
302 complain_overflow_bitfield, /* complain_on_overflow */
303 bfd_elf_generic_reloc, /* special_function */
304 "R_860_COPY", /* name */
305 TRUE, /* partial_inplace */
306 0xffffffff, /* src_mask */
307 0xffffffff, /* dst_mask */
308 FALSE), /* pcrel_offset */
309
310 HOWTO (R_860_GLOB_DAT, /* type */
311 0, /* rightshift */
312 2, /* size (0 = byte, 1 = short, 2 = long) */
313 32, /* bitsize */
314 FALSE, /* pc_relative */
315 0, /* bitpos */
316 complain_overflow_bitfield, /* complain_on_overflow */
317 bfd_elf_generic_reloc, /* special_function */
318 "R_860_GLOB_DAT", /* name */
319 TRUE, /* partial_inplace */
320 0xffffffff, /* src_mask */
321 0xffffffff, /* dst_mask */
322 FALSE), /* pcrel_offset */
323
324 HOWTO (R_860_JUMP_SLOT, /* type */
325 0, /* rightshift */
326 2, /* size (0 = byte, 1 = short, 2 = long) */
327 32, /* bitsize */
328 FALSE, /* pc_relative */
329 0, /* bitpos */
330 complain_overflow_bitfield, /* complain_on_overflow */
331 bfd_elf_generic_reloc, /* special_function */
332 "R_860_JUMP_SLOT", /* name */
333 TRUE, /* partial_inplace */
334 0xffffffff, /* src_mask */
335 0xffffffff, /* dst_mask */
336 FALSE), /* pcrel_offset */
337
338 HOWTO (R_860_RELATIVE, /* type */
339 0, /* rightshift */
340 2, /* size (0 = byte, 1 = short, 2 = long) */
341 32, /* bitsize */
342 FALSE, /* pc_relative */
343 0, /* bitpos */
344 complain_overflow_bitfield, /* complain_on_overflow */
345 bfd_elf_generic_reloc, /* special_function */
346 "R_860_RELATIVE", /* name */
347 TRUE, /* partial_inplace */
348 0xffffffff, /* src_mask */
349 0xffffffff, /* dst_mask */
350 FALSE), /* pcrel_offset */
351
352 /* A 26-bit PC-relative relocation. */
353 HOWTO (R_860_PC26, /* type */
354 2, /* rightshift */
355 2, /* size (0 = byte, 1 = short, 2 = long) */
356 26, /* bitsize */
357 TRUE, /* pc_relative */
358 0, /* bitpos */
359 complain_overflow_bitfield, /* complain_on_overflow */
360 i860_howto_pc26_reloc, /* special_function */
361 "R_860_PC26", /* name */
362 FALSE, /* partial_inplace */
363 0x3ffffff, /* src_mask */
364 0x3ffffff, /* dst_mask */
365 TRUE), /* pcrel_offset */
366
367 HOWTO (R_860_PLT26, /* type */
368 0, /* rightshift */
369 2, /* size (0 = byte, 1 = short, 2 = long) */
370 26, /* bitsize */
371 TRUE, /* pc_relative */
372 0, /* bitpos */
373 complain_overflow_bitfield, /* complain_on_overflow */
374 bfd_elf_generic_reloc, /* special_function */
375 "R_860_PLT26", /* name */
376 TRUE, /* partial_inplace */
377 0xffffffff, /* src_mask */
378 0xffffffff, /* dst_mask */
379 TRUE), /* pcrel_offset */
380
381 /* A 16-bit PC-relative relocation. */
382 HOWTO (R_860_PC16, /* type */
383 2, /* rightshift */
384 2, /* size (0 = byte, 1 = short, 2 = long) */
385 16, /* bitsize */
386 TRUE, /* pc_relative */
387 0, /* bitpos */
388 complain_overflow_bitfield, /* complain_on_overflow */
389 i860_howto_pc16_reloc, /* special_function */
390 "R_860_PC16", /* name */
391 FALSE, /* partial_inplace */
392 0x1f07ff, /* src_mask */
393 0x1f07ff, /* dst_mask */
394 TRUE), /* pcrel_offset */
395
396 HOWTO (R_860_LOW0, /* type */
397 0, /* rightshift */
398 2, /* size (0 = byte, 1 = short, 2 = long) */
399 16, /* bitsize */
400 FALSE, /* pc_relative */
401 0, /* bitpos */
402 complain_overflow_dont, /* complain_on_overflow */
403 bfd_elf_generic_reloc, /* special_function */
404 "R_860_LOW0", /* name */
405 FALSE, /* partial_inplace */
406 0xffff, /* src_mask */
407 0xffff, /* dst_mask */
408 FALSE), /* pcrel_offset */
409
410 HOWTO (R_860_SPLIT0, /* type */
411 0, /* rightshift */
412 2, /* size (0 = byte, 1 = short, 2 = long) */
413 16, /* bitsize */
414 FALSE, /* pc_relative */
415 0, /* bitpos */
416 complain_overflow_dont, /* complain_on_overflow */
417 i860_howto_splitn_reloc, /* special_function */
418 "R_860_SPLIT0", /* name */
419 FALSE, /* partial_inplace */
420 0x1f07ff, /* src_mask */
421 0x1f07ff, /* dst_mask */
422 FALSE), /* pcrel_offset */
423
424 HOWTO (R_860_LOW1, /* type */
425 0, /* rightshift */
426 2, /* size (0 = byte, 1 = short, 2 = long) */
427 16, /* bitsize */
428 FALSE, /* pc_relative */
429 0, /* bitpos */
430 complain_overflow_dont, /* complain_on_overflow */
431 bfd_elf_generic_reloc, /* special_function */
432 "R_860_LOW1", /* name */
433 FALSE, /* partial_inplace */
434 0xfffe, /* src_mask */
435 0xfffe, /* dst_mask */
436 FALSE), /* pcrel_offset */
437
438 HOWTO (R_860_SPLIT1, /* type */
439 0, /* rightshift */
440 2, /* size (0 = byte, 1 = short, 2 = long) */
441 16, /* bitsize */
442 FALSE, /* pc_relative */
443 0, /* bitpos */
444 complain_overflow_dont, /* complain_on_overflow */
445 i860_howto_splitn_reloc, /* special_function */
446 "R_860_SPLIT1", /* name */
447 FALSE, /* partial_inplace */
448 0x1f07fe, /* src_mask */
449 0x1f07fe, /* dst_mask */
450 FALSE), /* pcrel_offset */
451
452 HOWTO (R_860_LOW2, /* type */
453 0, /* rightshift */
454 2, /* size (0 = byte, 1 = short, 2 = long) */
455 16, /* bitsize */
456 FALSE, /* pc_relative */
457 0, /* bitpos */
458 complain_overflow_dont, /* complain_on_overflow */
459 bfd_elf_generic_reloc, /* special_function */
460 "R_860_LOW2", /* name */
461 FALSE, /* partial_inplace */
462 0xfffc, /* src_mask */
463 0xfffc, /* dst_mask */
464 FALSE), /* pcrel_offset */
465
466 HOWTO (R_860_SPLIT2, /* type */
467 0, /* rightshift */
468 2, /* size (0 = byte, 1 = short, 2 = long) */
469 16, /* bitsize */
470 FALSE, /* pc_relative */
471 0, /* bitpos */
472 complain_overflow_dont, /* complain_on_overflow */
473 i860_howto_splitn_reloc, /* special_function */
474 "R_860_SPLIT2", /* name */
475 FALSE, /* partial_inplace */
476 0x1f07fc, /* src_mask */
477 0x1f07fc, /* dst_mask */
478 FALSE), /* pcrel_offset */
479
480 HOWTO (R_860_LOW3, /* type */
481 0, /* rightshift */
482 2, /* size (0 = byte, 1 = short, 2 = long) */
483 16, /* bitsize */
484 FALSE, /* pc_relative */
485 0, /* bitpos */
486 complain_overflow_dont, /* complain_on_overflow */
487 bfd_elf_generic_reloc, /* special_function */
488 "R_860_LOW3", /* name */
489 FALSE, /* partial_inplace */
490 0xfff8, /* src_mask */
491 0xfff8, /* dst_mask */
492 FALSE), /* pcrel_offset */
493
494 HOWTO (R_860_LOGOT0, /* type */
495 0, /* rightshift */
496 2, /* size (0 = byte, 1 = short, 2 = long) */
497 16, /* bitsize */
498 FALSE, /* pc_relative */
499 0, /* bitpos */
500 complain_overflow_dont, /* complain_on_overflow */
501 bfd_elf_generic_reloc, /* special_function */
502 "R_860_LOGOT0", /* name */
503 FALSE, /* partial_inplace */
504 0, /* src_mask */
505 0xffff, /* dst_mask */
506 TRUE), /* pcrel_offset */
507
508 HOWTO (R_860_SPGOT0, /* type */
509 0, /* rightshift */
510 2, /* size (0 = byte, 1 = short, 2 = long) */
511 16, /* bitsize */
512 FALSE, /* pc_relative */
513 0, /* bitpos */
514 complain_overflow_dont, /* complain_on_overflow */
515 bfd_elf_generic_reloc, /* special_function */
516 "R_860_SPGOT0", /* name */
517 FALSE, /* partial_inplace */
518 0, /* src_mask */
519 0xffff, /* dst_mask */
520 TRUE), /* pcrel_offset */
521
522 HOWTO (R_860_LOGOT1, /* type */
523 0, /* rightshift */
524 2, /* size (0 = byte, 1 = short, 2 = long) */
525 16, /* bitsize */
526 FALSE, /* pc_relative */
527 0, /* bitpos */
528 complain_overflow_dont, /* complain_on_overflow */
529 bfd_elf_generic_reloc, /* special_function */
530 "R_860_LOGOT1", /* name */
531 FALSE, /* partial_inplace */
532 0, /* src_mask */
533 0xffff, /* dst_mask */
534 TRUE), /* pcrel_offset */
535
536 HOWTO (R_860_SPGOT1, /* type */
537 0, /* rightshift */
538 2, /* size (0 = byte, 1 = short, 2 = long) */
539 16, /* bitsize */
540 FALSE, /* pc_relative */
541 0, /* bitpos */
542 complain_overflow_dont, /* complain_on_overflow */
543 bfd_elf_generic_reloc, /* special_function */
544 "R_860_SPGOT1", /* name */
545 FALSE, /* partial_inplace */
546 0, /* src_mask */
547 0xffff, /* dst_mask */
548 TRUE), /* pcrel_offset */
549
550 HOWTO (R_860_LOGOTOFF0, /* type */
551 0, /* rightshift */
552 2, /* size (0 = byte, 1 = short, 2 = long) */
553 32, /* bitsize */
554 FALSE, /* pc_relative */
555 0, /* bitpos */
556 complain_overflow_dont, /* complain_on_overflow */
557 bfd_elf_generic_reloc, /* special_function */
558 "R_860_LOGOTOFF0", /* name */
559 TRUE, /* partial_inplace */
560 0xffffffff, /* src_mask */
561 0xffffffff, /* dst_mask */
562 FALSE), /* pcrel_offset */
563
564 HOWTO (R_860_SPGOTOFF0, /* type */
565 0, /* rightshift */
566 2, /* size (0 = byte, 1 = short, 2 = long) */
567 32, /* bitsize */
568 FALSE, /* pc_relative */
569 0, /* bitpos */
570 complain_overflow_dont, /* complain_on_overflow */
571 bfd_elf_generic_reloc, /* special_function */
572 "R_860_SPGOTOFF0", /* name */
573 TRUE, /* partial_inplace */
574 0xffffffff, /* src_mask */
575 0xffffffff, /* dst_mask */
576 FALSE), /* pcrel_offset */
577
578 HOWTO (R_860_LOGOTOFF1, /* type */
579 0, /* rightshift */
580 2, /* size (0 = byte, 1 = short, 2 = long) */
581 32, /* bitsize */
582 FALSE, /* pc_relative */
583 0, /* bitpos */
584 complain_overflow_dont, /* complain_on_overflow */
585 bfd_elf_generic_reloc, /* special_function */
586 "R_860_LOGOTOFF1", /* name */
587 TRUE, /* partial_inplace */
588 0xffffffff, /* src_mask */
589 0xffffffff, /* dst_mask */
590 FALSE), /* pcrel_offset */
591
592 HOWTO (R_860_SPGOTOFF1, /* type */
593 0, /* rightshift */
594 2, /* size (0 = byte, 1 = short, 2 = long) */
595 32, /* bitsize */
596 FALSE, /* pc_relative */
597 0, /* bitpos */
598 complain_overflow_dont, /* complain_on_overflow */
599 bfd_elf_generic_reloc, /* special_function */
600 "R_860_SPGOTOFF1", /* name */
601 TRUE, /* partial_inplace */
602 0xffffffff, /* src_mask */
603 0xffffffff, /* dst_mask */
604 FALSE), /* pcrel_offset */
605
606 HOWTO (R_860_LOGOTOFF2, /* type */
607 0, /* rightshift */
608 2, /* size (0 = byte, 1 = short, 2 = long) */
609 32, /* bitsize */
610 FALSE, /* pc_relative */
611 0, /* bitpos */
612 complain_overflow_dont, /* complain_on_overflow */
613 bfd_elf_generic_reloc, /* special_function */
614 "R_860_LOGOTOFF2", /* name */
615 TRUE, /* partial_inplace */
616 0xffffffff, /* src_mask */
617 0xffffffff, /* dst_mask */
618 FALSE), /* pcrel_offset */
619
620 HOWTO (R_860_LOGOTOFF3, /* type */
621 0, /* rightshift */
622 2, /* size (0 = byte, 1 = short, 2 = long) */
623 32, /* bitsize */
624 FALSE, /* pc_relative */
625 0, /* bitpos */
626 complain_overflow_dont, /* complain_on_overflow */
627 bfd_elf_generic_reloc, /* special_function */
628 "R_860_LOGOTOFF3", /* name */
629 TRUE, /* partial_inplace */
630 0xffffffff, /* src_mask */
631 0xffffffff, /* dst_mask */
632 FALSE), /* pcrel_offset */
633
634 HOWTO (R_860_LOPC, /* type */
635 0, /* rightshift */
636 2, /* size (0 = byte, 1 = short, 2 = long) */
637 16, /* bitsize */
638 TRUE, /* pc_relative */
639 0, /* bitpos */
640 complain_overflow_bitfield, /* complain_on_overflow */
641 bfd_elf_generic_reloc, /* special_function */
642 "R_860_LOPC", /* name */
643 FALSE, /* partial_inplace */
644 0xffff, /* src_mask */
645 0xffff, /* dst_mask */
646 TRUE), /* pcrel_offset */
647
648 HOWTO (R_860_HIGHADJ, /* type */
649 0, /* rightshift */
650 2, /* size (0 = byte, 1 = short, 2 = long) */
651 16, /* bitsize */
652 FALSE, /* pc_relative */
653 0, /* bitpos */
654 complain_overflow_dont, /* complain_on_overflow */
655 i860_howto_highadj_reloc, /* special_function */
656 "R_860_HIGHADJ", /* name */
657 FALSE, /* partial_inplace */
658 0xffff, /* src_mask */
659 0xffff, /* dst_mask */
660 FALSE), /* pcrel_offset */
661
662 HOWTO (R_860_HAGOT, /* type */
663 0, /* rightshift */
664 2, /* size (0 = byte, 1 = short, 2 = long) */
665 16, /* bitsize */
666 FALSE, /* pc_relative */
667 0, /* bitpos */
668 complain_overflow_dont, /* complain_on_overflow */
669 bfd_elf_generic_reloc, /* special_function */
670 "R_860_HAGOT", /* name */
671 FALSE, /* partial_inplace */
672 0, /* src_mask */
673 0xffff, /* dst_mask */
674 TRUE), /* pcrel_offset */
675
676 HOWTO (R_860_HAGOTOFF, /* type */
677 0, /* rightshift */
678 2, /* size (0 = byte, 1 = short, 2 = long) */
679 32, /* bitsize */
680 FALSE, /* pc_relative */
681 0, /* bitpos */
682 complain_overflow_dont, /* complain_on_overflow */
683 bfd_elf_generic_reloc, /* special_function */
684 "R_860_HAGOTOFF", /* name */
685 TRUE, /* partial_inplace */
686 0xffffffff, /* src_mask */
687 0xffffffff, /* dst_mask */
688 FALSE), /* pcrel_offset */
689
690 HOWTO (R_860_HAPC, /* type */
691 0, /* rightshift */
692 2, /* size (0 = byte, 1 = short, 2 = long) */
693 16, /* bitsize */
694 TRUE, /* pc_relative */
695 0, /* bitpos */
696 complain_overflow_bitfield, /* complain_on_overflow */
697 bfd_elf_generic_reloc, /* special_function */
698 "R_860_HAPC", /* name */
699 FALSE, /* partial_inplace */
700 0xffff, /* src_mask */
701 0xffff, /* dst_mask */
702 TRUE), /* pcrel_offset */
703
704 HOWTO (R_860_HIGH, /* type */
705 16, /* rightshift */
706 2, /* size (0 = byte, 1 = short, 2 = long) */
707 16, /* bitsize */
708 FALSE, /* pc_relative */
709 0, /* bitpos */
710 complain_overflow_dont, /* complain_on_overflow */
711 bfd_elf_generic_reloc, /* special_function */
712 "R_860_HIGH", /* name */
713 FALSE, /* partial_inplace */
714 0xffff, /* src_mask */
715 0xffff, /* dst_mask */
716 FALSE), /* pcrel_offset */
717
718 HOWTO (R_860_HIGOT, /* type */
719 0, /* rightshift */
720 2, /* size (0 = byte, 1 = short, 2 = long) */
721 16, /* bitsize */
722 FALSE, /* pc_relative */
723 0, /* bitpos */
724 complain_overflow_dont, /* complain_on_overflow */
725 bfd_elf_generic_reloc, /* special_function */
726 "R_860_HIGOT", /* name */
727 FALSE, /* partial_inplace */
728 0, /* src_mask */
729 0xffff, /* dst_mask */
730 TRUE), /* pcrel_offset */
731
732 HOWTO (R_860_HIGOTOFF, /* type */
733 0, /* rightshift */
734 2, /* size (0 = byte, 1 = short, 2 = long) */
735 32, /* bitsize */
736 FALSE, /* pc_relative */
737 0, /* bitpos */
738 complain_overflow_dont, /* complain_on_overflow */
739 bfd_elf_generic_reloc, /* special_function */
740 "R_860_HIGOTOFF", /* name */
741 TRUE, /* partial_inplace */
742 0xffffffff, /* src_mask */
743 0xffffffff, /* dst_mask */
744 FALSE), /* pcrel_offset */
745 };
746 \f
747 static unsigned char elf_code_to_howto_index[R_860_max + 1];
748
749 static reloc_howto_type *
750 lookup_howto (unsigned int rtype)
751 {
752 static int initialized = 0;
753 int i;
754 int howto_tbl_size = (int) (sizeof (elf32_i860_howto_table)
755 / sizeof (elf32_i860_howto_table[0]));
756
757 if (! initialized)
758 {
759 initialized = 1;
760 memset (elf_code_to_howto_index, 0xff,
761 sizeof (elf_code_to_howto_index));
762 for (i = 0; i < howto_tbl_size; i++)
763 elf_code_to_howto_index[elf32_i860_howto_table[i].type] = i;
764 }
765
766 BFD_ASSERT (rtype <= R_860_max);
767 i = elf_code_to_howto_index[rtype];
768 if (i >= howto_tbl_size)
769 return 0;
770 return elf32_i860_howto_table + i;
771 }
772
773 /* Given a BFD reloc, return the matching HOWTO structure. */
774 static reloc_howto_type *
775 elf32_i860_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
776 bfd_reloc_code_real_type code)
777 {
778 unsigned int rtype;
779
780 switch (code)
781 {
782 case BFD_RELOC_NONE:
783 rtype = R_860_NONE;
784 break;
785 case BFD_RELOC_32:
786 rtype = R_860_32;
787 break;
788 case BFD_RELOC_860_COPY:
789 rtype = R_860_COPY;
790 break;
791 case BFD_RELOC_860_GLOB_DAT:
792 rtype = R_860_GLOB_DAT;
793 break;
794 case BFD_RELOC_860_JUMP_SLOT:
795 rtype = R_860_JUMP_SLOT;
796 break;
797 case BFD_RELOC_860_RELATIVE:
798 rtype = R_860_RELATIVE;
799 break;
800 case BFD_RELOC_860_PC26:
801 rtype = R_860_PC26;
802 break;
803 case BFD_RELOC_860_PLT26:
804 rtype = R_860_PLT26;
805 break;
806 case BFD_RELOC_860_PC16:
807 rtype = R_860_PC16;
808 break;
809 case BFD_RELOC_860_LOW0:
810 rtype = R_860_LOW0;
811 break;
812 case BFD_RELOC_860_SPLIT0:
813 rtype = R_860_SPLIT0;
814 break;
815 case BFD_RELOC_860_LOW1:
816 rtype = R_860_LOW1;
817 break;
818 case BFD_RELOC_860_SPLIT1:
819 rtype = R_860_SPLIT1;
820 break;
821 case BFD_RELOC_860_LOW2:
822 rtype = R_860_LOW2;
823 break;
824 case BFD_RELOC_860_SPLIT2:
825 rtype = R_860_SPLIT2;
826 break;
827 case BFD_RELOC_860_LOW3:
828 rtype = R_860_LOW3;
829 break;
830 case BFD_RELOC_860_LOGOT0:
831 rtype = R_860_LOGOT0;
832 break;
833 case BFD_RELOC_860_SPGOT0:
834 rtype = R_860_SPGOT0;
835 break;
836 case BFD_RELOC_860_LOGOT1:
837 rtype = R_860_LOGOT1;
838 break;
839 case BFD_RELOC_860_SPGOT1:
840 rtype = R_860_SPGOT1;
841 break;
842 case BFD_RELOC_860_LOGOTOFF0:
843 rtype = R_860_LOGOTOFF0;
844 break;
845 case BFD_RELOC_860_SPGOTOFF0:
846 rtype = R_860_SPGOTOFF0;
847 break;
848 case BFD_RELOC_860_LOGOTOFF1:
849 rtype = R_860_LOGOTOFF1;
850 break;
851 case BFD_RELOC_860_SPGOTOFF1:
852 rtype = R_860_SPGOTOFF1;
853 break;
854 case BFD_RELOC_860_LOGOTOFF2:
855 rtype = R_860_LOGOTOFF2;
856 break;
857 case BFD_RELOC_860_LOGOTOFF3:
858 rtype = R_860_LOGOTOFF3;
859 break;
860 case BFD_RELOC_860_LOPC:
861 rtype = R_860_LOPC;
862 break;
863 case BFD_RELOC_860_HIGHADJ:
864 rtype = R_860_HIGHADJ;
865 break;
866 case BFD_RELOC_860_HAGOT:
867 rtype = R_860_HAGOT;
868 break;
869 case BFD_RELOC_860_HAGOTOFF:
870 rtype = R_860_HAGOTOFF;
871 break;
872 case BFD_RELOC_860_HAPC:
873 rtype = R_860_HAPC;
874 break;
875 case BFD_RELOC_860_HIGH:
876 rtype = R_860_HIGH;
877 break;
878 case BFD_RELOC_860_HIGOT:
879 rtype = R_860_HIGOT;
880 break;
881 case BFD_RELOC_860_HIGOTOFF:
882 rtype = R_860_HIGOTOFF;
883 break;
884 default:
885 rtype = 0;
886 break;
887 }
888 return lookup_howto (rtype);
889 }
890
891 static reloc_howto_type *
892 elf32_i860_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
893 const char *r_name)
894 {
895 unsigned int i;
896
897 for (i = 0;
898 i < (sizeof (elf32_i860_howto_table)
899 / sizeof (elf32_i860_howto_table[0]));
900 i++)
901 if (elf32_i860_howto_table[i].name != NULL
902 && strcasecmp (elf32_i860_howto_table[i].name, r_name) == 0)
903 return &elf32_i860_howto_table[i];
904
905 return NULL;
906 }
907
908 /* Given a ELF reloc, return the matching HOWTO structure. */
909 static void
910 elf32_i860_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
911 arelent *bfd_reloc,
912 Elf_Internal_Rela *elf_reloc)
913 {
914 bfd_reloc->howto
915 = lookup_howto ((unsigned) ELF32_R_TYPE (elf_reloc->r_info));
916 }
917 \f
918 /* Specialized relocation handler for R_860_SPLITn. These relocations
919 involves a 16-bit field that is split into two contiguous parts. */
920 static bfd_reloc_status_type
921 elf32_i860_relocate_splitn (bfd *input_bfd,
922 Elf_Internal_Rela *rello,
923 bfd_byte *contents,
924 bfd_vma value)
925 {
926 bfd_vma insn;
927 reloc_howto_type *howto;
928 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
929 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
930
931 /* Relocate. */
932 value += rello->r_addend;
933
934 /* Separate the fields and insert. */
935 value = (((value & 0xf800) << 5) | (value & 0x7ff)) & howto->dst_mask;
936 insn = (insn & ~howto->dst_mask) | value;
937
938 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
939 return bfd_reloc_ok;
940 }
941
942 /* Specialized relocation handler for R_860_PC16. This relocation
943 involves a 16-bit, PC-relative field that is split into two contiguous
944 parts. */
945 static bfd_reloc_status_type
946 elf32_i860_relocate_pc16 (bfd *input_bfd,
947 asection *input_section,
948 Elf_Internal_Rela *rello,
949 bfd_byte *contents,
950 bfd_vma value)
951 {
952 bfd_vma insn;
953 reloc_howto_type *howto;
954 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
955 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
956
957 /* Adjust for PC-relative relocation. */
958 value -= (input_section->output_section->vma
959 + input_section->output_offset);
960 value -= rello->r_offset;
961
962 /* Relocate. */
963 value += rello->r_addend;
964
965 /* Adjust the value by 4, then separate the fields and insert. */
966 value = (value - 4) >> howto->rightshift;
967 value = (((value & 0xf800) << 5) | (value & 0x7ff)) & howto->dst_mask;
968 insn = (insn & ~howto->dst_mask) | value;
969
970 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
971 return bfd_reloc_ok;
972
973 }
974
975 /* Specialized relocation handler for R_860_PC26. This relocation
976 involves a 26-bit, PC-relative field which must be adjusted by 4. */
977 static bfd_reloc_status_type
978 elf32_i860_relocate_pc26 (bfd *input_bfd,
979 asection *input_section,
980 Elf_Internal_Rela *rello,
981 bfd_byte *contents,
982 bfd_vma value)
983 {
984 bfd_vma insn;
985 reloc_howto_type *howto;
986 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
987 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
988
989 /* Adjust for PC-relative relocation. */
990 value -= (input_section->output_section->vma
991 + input_section->output_offset);
992 value -= rello->r_offset;
993
994 /* Relocate. */
995 value += rello->r_addend;
996
997 /* Adjust value by 4 and insert the field. */
998 value = ((value - 4) >> howto->rightshift) & howto->dst_mask;
999 insn = (insn & ~howto->dst_mask) | value;
1000
1001 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
1002 return bfd_reloc_ok;
1003
1004 }
1005
1006 /* Specialized relocation handler for R_860_HIGHADJ. */
1007 static bfd_reloc_status_type
1008 elf32_i860_relocate_highadj (bfd *input_bfd,
1009 Elf_Internal_Rela *rel,
1010 bfd_byte *contents,
1011 bfd_vma value)
1012 {
1013 bfd_vma insn;
1014
1015 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
1016
1017 value += rel->r_addend;
1018 value += 0x8000;
1019 value = ((value >> 16) & 0xffff);
1020
1021 insn = (insn & 0xffff0000) | value;
1022
1023 bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
1024 return bfd_reloc_ok;
1025 }
1026
1027 /* Perform a single relocation. By default we use the standard BFD
1028 routines. However, we handle some specially. */
1029 static bfd_reloc_status_type
1030 i860_final_link_relocate (reloc_howto_type *howto,
1031 bfd *input_bfd,
1032 asection *input_section,
1033 bfd_byte *contents,
1034 Elf_Internal_Rela *rel,
1035 bfd_vma relocation)
1036 {
1037 return _bfd_final_link_relocate (howto, input_bfd, input_section,
1038 contents, rel->r_offset, relocation,
1039 rel->r_addend);
1040 }
1041
1042 /* Relocate an i860 ELF section.
1043
1044 This is boiler-plate code copied from fr30.
1045
1046 The RELOCATE_SECTION function is called by the new ELF backend linker
1047 to handle the relocations for a section.
1048
1049 The relocs are always passed as Rela structures; if the section
1050 actually uses Rel structures, the r_addend field will always be
1051 zero.
1052
1053 This function is responsible for adjusting the section contents as
1054 necessary, and (if using Rela relocs and generating a relocatable
1055 output file) adjusting the reloc addend as necessary.
1056
1057 This function does not have to worry about setting the reloc
1058 address or the reloc symbol index.
1059
1060 LOCAL_SYMS is a pointer to the swapped in local symbols.
1061
1062 LOCAL_SECTIONS is an array giving the section in the input file
1063 corresponding to the st_shndx field of each local symbol.
1064
1065 The global hash table entry for the global symbols can be found
1066 via elf_sym_hashes (input_bfd).
1067
1068 When generating relocatable output, this function must handle
1069 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
1070 going to be the section symbol corresponding to the output
1071 section, which means that the addend must be adjusted
1072 accordingly. */
1073 static bfd_boolean
1074 elf32_i860_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
1075 struct bfd_link_info *info,
1076 bfd *input_bfd,
1077 asection *input_section,
1078 bfd_byte *contents,
1079 Elf_Internal_Rela *relocs,
1080 Elf_Internal_Sym *local_syms,
1081 asection **local_sections)
1082 {
1083 Elf_Internal_Shdr *symtab_hdr;
1084 struct elf_link_hash_entry **sym_hashes;
1085 Elf_Internal_Rela *rel;
1086 Elf_Internal_Rela *relend;
1087
1088 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1089 sym_hashes = elf_sym_hashes (input_bfd);
1090 relend = relocs + input_section->reloc_count;
1091
1092 for (rel = relocs; rel < relend; rel ++)
1093 {
1094 reloc_howto_type * howto;
1095 unsigned long r_symndx;
1096 Elf_Internal_Sym * sym;
1097 asection * sec;
1098 struct elf_link_hash_entry * h;
1099 bfd_vma relocation;
1100 bfd_reloc_status_type r;
1101 const char * name = NULL;
1102 int r_type;
1103
1104 r_type = ELF32_R_TYPE (rel->r_info);
1105 r_symndx = ELF32_R_SYM (rel->r_info);
1106
1107 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
1108 h = NULL;
1109 sym = NULL;
1110 sec = NULL;
1111
1112 if (r_symndx < symtab_hdr->sh_info)
1113 {
1114 sym = local_syms + r_symndx;
1115 sec = local_sections [r_symndx];
1116 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1117
1118 name = bfd_elf_string_from_elf_section
1119 (input_bfd, symtab_hdr->sh_link, sym->st_name);
1120 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
1121 }
1122 else
1123 {
1124 bfd_boolean unresolved_reloc, warned;
1125
1126 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1127 r_symndx, symtab_hdr, sym_hashes,
1128 h, sec, relocation,
1129 unresolved_reloc, warned);
1130 }
1131
1132 if (sec != NULL && discarded_section (sec))
1133 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
1134 rel, 1, relend, howto, 0, contents);
1135
1136 if (info->relocatable)
1137 continue;
1138
1139 switch (r_type)
1140 {
1141 default:
1142 r = i860_final_link_relocate (howto, input_bfd, input_section,
1143 contents, rel, relocation);
1144 break;
1145
1146 case R_860_HIGHADJ:
1147 r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
1148 relocation);
1149 break;
1150
1151 case R_860_PC16:
1152 r = elf32_i860_relocate_pc16 (input_bfd, input_section, rel,
1153 contents, relocation);
1154 break;
1155
1156 case R_860_PC26:
1157 r = elf32_i860_relocate_pc26 (input_bfd, input_section, rel,
1158 contents, relocation);
1159 break;
1160
1161 case R_860_SPLIT0:
1162 case R_860_SPLIT1:
1163 case R_860_SPLIT2:
1164 r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
1165 relocation);
1166 break;
1167
1168 /* We do not yet handle GOT/PLT/Dynamic relocations. */
1169 case R_860_COPY:
1170 case R_860_GLOB_DAT:
1171 case R_860_JUMP_SLOT:
1172 case R_860_RELATIVE:
1173 case R_860_PLT26:
1174 case R_860_LOGOT0:
1175 case R_860_SPGOT0:
1176 case R_860_LOGOT1:
1177 case R_860_SPGOT1:
1178 case R_860_LOGOTOFF0:
1179 case R_860_SPGOTOFF0:
1180 case R_860_LOGOTOFF1:
1181 case R_860_SPGOTOFF1:
1182 case R_860_LOGOTOFF2:
1183 case R_860_LOGOTOFF3:
1184 case R_860_LOPC:
1185 case R_860_HAGOT:
1186 case R_860_HAGOTOFF:
1187 case R_860_HAPC:
1188 case R_860_HIGOT:
1189 case R_860_HIGOTOFF:
1190 r = bfd_reloc_notsupported;
1191 break;
1192 }
1193
1194 if (r != bfd_reloc_ok)
1195 {
1196 const char * msg = (const char *) NULL;
1197
1198 switch (r)
1199 {
1200 case bfd_reloc_overflow:
1201 r = info->callbacks->reloc_overflow
1202 (info, (h ? &h->root : NULL), name, howto->name,
1203 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
1204 break;
1205
1206 case bfd_reloc_undefined:
1207 r = info->callbacks->undefined_symbol
1208 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
1209 break;
1210
1211 case bfd_reloc_outofrange:
1212 msg = _("internal error: out of range error");
1213 break;
1214
1215 case bfd_reloc_notsupported:
1216 msg = _("internal error: unsupported relocation error");
1217 break;
1218
1219 case bfd_reloc_dangerous:
1220 msg = _("internal error: dangerous relocation");
1221 break;
1222
1223 default:
1224 msg = _("internal error: unknown error");
1225 break;
1226 }
1227
1228 if (msg)
1229 r = info->callbacks->warning
1230 (info, msg, name, input_bfd, input_section, rel->r_offset);
1231
1232 if (! r)
1233 return FALSE;
1234 }
1235 }
1236
1237 return TRUE;
1238 }
1239
1240 /* Return whether a symbol name implies a local label. SVR4/860 compilers
1241 generate labels of the form ".ep.function_name" to denote the end of a
1242 function prolog. These should be local.
1243 ??? Do any other SVR4 compilers have this convention? If so, this should
1244 be added to the generic routine. */
1245 static bfd_boolean
1246 elf32_i860_is_local_label_name (bfd *abfd, const char *name)
1247 {
1248 if (name[0] == '.' && name[1] == 'e' && name[2] == 'p' && name[3] == '.')
1249 return TRUE;
1250
1251 return _bfd_elf_is_local_label_name (abfd, name);
1252 }
1253 \f
1254 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1255 #define TARGET_BIG_NAME "elf32-i860"
1256 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1257 #define TARGET_LITTLE_NAME "elf32-i860-little"
1258 #define ELF_ARCH bfd_arch_i860
1259 #define ELF_MACHINE_CODE EM_860
1260 #define ELF_MAXPAGESIZE 4096
1261
1262 #define elf_backend_rela_normal 1
1263 #define elf_info_to_howto_rel NULL
1264 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1265 #define elf_backend_relocate_section elf32_i860_relocate_section
1266 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1267 #define bfd_elf32_bfd_reloc_name_lookup elf32_i860_reloc_name_lookup
1268 #define bfd_elf32_bfd_is_local_label_name elf32_i860_is_local_label_name
1269
1270 #include "elf32-target.h"
This page took 0.057431 seconds and 4 git commands to generate.