1
/* Intel i860 specific support for 32-bit ELF.
2
Copyright 1993, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008,
4
Free Software Foundation, Inc.
6
Full i860 support contributed by Jason Eckhardt <jle@cygnus.com>.
8
This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
31
/* special_function for R_860_PC26 relocation. */
32
static bfd_reloc_status_type
33
i860_howto_pc26_reloc (bfd *abfd ATTRIBUTE_UNUSED,
36
void *data ATTRIBUTE_UNUSED,
37
asection *input_section,
39
char **error_message ATTRIBUTE_UNUSED)
45
if (output_bfd != NULL
46
&& (symbol->flags & BSF_SECTION_SYM) == 0
47
&& (! reloc_entry->howto->partial_inplace
48
|| reloc_entry->addend == 0))
50
reloc_entry->address += input_section->output_offset;
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;
59
if (bfd_is_com_section (symbol->section))
62
relocation = symbol->value;
64
relocation += symbol->section->output_section->vma;
65
relocation += symbol->section->output_offset;
66
relocation += reloc_entry->addend;
68
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
69
return bfd_reloc_outofrange;
71
/* Adjust for PC-relative relocation. */
72
relocation -= (input_section->output_section->vma
73
+ input_section->output_offset
74
+ reloc_entry->address
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;
82
addr = (bfd_byte *) data + reloc_entry->address;
83
insn = bfd_get_32 (abfd, addr);
85
relocation >>= reloc_entry->howto->rightshift;
86
insn = (insn & ~reloc_entry->howto->dst_mask)
87
| (relocation & reloc_entry->howto->dst_mask);
89
bfd_put_32 (abfd, (bfd_vma) insn, addr);
94
/* special_function for R_860_PC16 relocation. */
95
static bfd_reloc_status_type
96
i860_howto_pc16_reloc (bfd *abfd,
100
asection *input_section,
102
char **error_message ATTRIBUTE_UNUSED)
108
if (output_bfd != NULL
109
&& (symbol->flags & BSF_SECTION_SYM) == 0
110
&& (! reloc_entry->howto->partial_inplace
111
|| reloc_entry->addend == 0))
113
reloc_entry->address += input_section->output_offset;
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;
122
if (bfd_is_com_section (symbol->section))
125
relocation = symbol->value;
127
relocation += symbol->section->output_section->vma;
128
relocation += symbol->section->output_offset;
129
relocation += reloc_entry->addend;
131
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
132
return bfd_reloc_outofrange;
134
/* Adjust for PC-relative relocation. */
135
relocation -= (input_section->output_section->vma
136
+ input_section->output_offset
137
+ reloc_entry->address
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;
145
addr = (bfd_byte *) data + reloc_entry->address;
146
insn = bfd_get_32 (abfd, addr);
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;
153
bfd_put_32 (abfd, (bfd_vma) insn, addr);
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,
164
asection *input_section,
166
char **error_message ATTRIBUTE_UNUSED)
172
if (output_bfd != NULL
173
&& (symbol->flags & BSF_SECTION_SYM) == 0
174
&& (! reloc_entry->howto->partial_inplace
175
|| reloc_entry->addend == 0))
177
reloc_entry->address += input_section->output_offset;
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;
186
if (bfd_is_com_section (symbol->section))
189
relocation = symbol->value;
191
relocation += symbol->section->output_section->vma;
192
relocation += symbol->section->output_offset;
193
relocation += reloc_entry->addend;
194
relocation += 0x8000;
196
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
197
return bfd_reloc_outofrange;
199
addr = (bfd_byte *) data + reloc_entry->address;
200
insn = bfd_get_32 (abfd, addr);
202
relocation = ((relocation >> 16) & 0xffff);
204
insn = (insn & 0xffff0000) | relocation;
206
bfd_put_32 (abfd, (bfd_vma) insn, addr);
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,
217
asection *input_section,
219
char **error_message ATTRIBUTE_UNUSED)
225
if (output_bfd != NULL
226
&& (symbol->flags & BSF_SECTION_SYM) == 0
227
&& (! reloc_entry->howto->partial_inplace
228
|| reloc_entry->addend == 0))
230
reloc_entry->address += input_section->output_offset;
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;
239
if (bfd_is_com_section (symbol->section))
242
relocation = symbol->value;
244
relocation += symbol->section->output_section->vma;
245
relocation += symbol->section->output_offset;
246
relocation += reloc_entry->addend;
248
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
249
return bfd_reloc_outofrange;
251
addr = (bfd_byte *) data + reloc_entry->address;
252
insn = bfd_get_32 (abfd, addr);
254
relocation = (((relocation & 0xf800) << 5) | (relocation & 0x7ff))
255
& reloc_entry->howto->dst_mask;
256
insn = (insn & ~reloc_entry->howto->dst_mask) | relocation;
258
bfd_put_32 (abfd, (bfd_vma) insn, addr);
263
/* This howto table is preliminary. */
264
static reloc_howto_type elf32_i860_howto_table [] =
266
/* This relocation does nothing. */
267
HOWTO (R_860_NONE, /* type */
269
2, /* size (0 = byte, 1 = short, 2 = long) */
271
FALSE, /* pc_relative */
273
complain_overflow_bitfield, /* complain_on_overflow */
274
bfd_elf_generic_reloc, /* special_function */
275
"R_860_NONE", /* name */
276
FALSE, /* partial_inplace */
279
FALSE), /* pcrel_offset */
281
/* A 32-bit absolute relocation. */
282
HOWTO (R_860_32, /* type */
284
2, /* size (0 = byte, 1 = short, 2 = long) */
286
FALSE, /* pc_relative */
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 */
296
HOWTO (R_860_COPY, /* type */
298
2, /* size (0 = byte, 1 = short, 2 = long) */
300
FALSE, /* pc_relative */
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 */
310
HOWTO (R_860_GLOB_DAT, /* type */
312
2, /* size (0 = byte, 1 = short, 2 = long) */
314
FALSE, /* pc_relative */
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 */
324
HOWTO (R_860_JUMP_SLOT, /* type */
326
2, /* size (0 = byte, 1 = short, 2 = long) */
328
FALSE, /* pc_relative */
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 */
338
HOWTO (R_860_RELATIVE, /* type */
340
2, /* size (0 = byte, 1 = short, 2 = long) */
342
FALSE, /* pc_relative */
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 */
352
/* A 26-bit PC-relative relocation. */
353
HOWTO (R_860_PC26, /* type */
355
2, /* size (0 = byte, 1 = short, 2 = long) */
357
TRUE, /* pc_relative */
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 */
367
HOWTO (R_860_PLT26, /* type */
369
2, /* size (0 = byte, 1 = short, 2 = long) */
371
TRUE, /* pc_relative */
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 */
381
/* A 16-bit PC-relative relocation. */
382
HOWTO (R_860_PC16, /* type */
384
2, /* size (0 = byte, 1 = short, 2 = long) */
386
TRUE, /* pc_relative */
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 */
396
HOWTO (R_860_LOW0, /* type */
398
2, /* size (0 = byte, 1 = short, 2 = long) */
400
FALSE, /* pc_relative */
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 */
410
HOWTO (R_860_SPLIT0, /* type */
412
2, /* size (0 = byte, 1 = short, 2 = long) */
414
FALSE, /* pc_relative */
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 */
424
HOWTO (R_860_LOW1, /* type */
426
2, /* size (0 = byte, 1 = short, 2 = long) */
428
FALSE, /* pc_relative */
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 */
438
HOWTO (R_860_SPLIT1, /* type */
440
2, /* size (0 = byte, 1 = short, 2 = long) */
442
FALSE, /* pc_relative */
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 */
452
HOWTO (R_860_LOW2, /* type */
454
2, /* size (0 = byte, 1 = short, 2 = long) */
456
FALSE, /* pc_relative */
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 */
466
HOWTO (R_860_SPLIT2, /* type */
468
2, /* size (0 = byte, 1 = short, 2 = long) */
470
FALSE, /* pc_relative */
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 */
480
HOWTO (R_860_LOW3, /* type */
482
2, /* size (0 = byte, 1 = short, 2 = long) */
484
FALSE, /* pc_relative */
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 */
494
HOWTO (R_860_LOGOT0, /* type */
496
2, /* size (0 = byte, 1 = short, 2 = long) */
498
FALSE, /* pc_relative */
500
complain_overflow_dont, /* complain_on_overflow */
501
bfd_elf_generic_reloc, /* special_function */
502
"R_860_LOGOT0", /* name */
503
FALSE, /* partial_inplace */
505
0xffff, /* dst_mask */
506
TRUE), /* pcrel_offset */
508
HOWTO (R_860_SPGOT0, /* type */
510
2, /* size (0 = byte, 1 = short, 2 = long) */
512
FALSE, /* pc_relative */
514
complain_overflow_dont, /* complain_on_overflow */
515
bfd_elf_generic_reloc, /* special_function */
516
"R_860_SPGOT0", /* name */
517
FALSE, /* partial_inplace */
519
0xffff, /* dst_mask */
520
TRUE), /* pcrel_offset */
522
HOWTO (R_860_LOGOT1, /* type */
524
2, /* size (0 = byte, 1 = short, 2 = long) */
526
FALSE, /* pc_relative */
528
complain_overflow_dont, /* complain_on_overflow */
529
bfd_elf_generic_reloc, /* special_function */
530
"R_860_LOGOT1", /* name */
531
FALSE, /* partial_inplace */
533
0xffff, /* dst_mask */
534
TRUE), /* pcrel_offset */
536
HOWTO (R_860_SPGOT1, /* type */
538
2, /* size (0 = byte, 1 = short, 2 = long) */
540
FALSE, /* pc_relative */
542
complain_overflow_dont, /* complain_on_overflow */
543
bfd_elf_generic_reloc, /* special_function */
544
"R_860_SPGOT1", /* name */
545
FALSE, /* partial_inplace */
547
0xffff, /* dst_mask */
548
TRUE), /* pcrel_offset */
550
HOWTO (R_860_LOGOTOFF0, /* type */
552
2, /* size (0 = byte, 1 = short, 2 = long) */
554
FALSE, /* pc_relative */
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 */
564
HOWTO (R_860_SPGOTOFF0, /* type */
566
2, /* size (0 = byte, 1 = short, 2 = long) */
568
FALSE, /* pc_relative */
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 */
578
HOWTO (R_860_LOGOTOFF1, /* type */
580
2, /* size (0 = byte, 1 = short, 2 = long) */
582
FALSE, /* pc_relative */
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 */
592
HOWTO (R_860_SPGOTOFF1, /* type */
594
2, /* size (0 = byte, 1 = short, 2 = long) */
596
FALSE, /* pc_relative */
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 */
606
HOWTO (R_860_LOGOTOFF2, /* type */
608
2, /* size (0 = byte, 1 = short, 2 = long) */
610
FALSE, /* pc_relative */
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 */
620
HOWTO (R_860_LOGOTOFF3, /* type */
622
2, /* size (0 = byte, 1 = short, 2 = long) */
624
FALSE, /* pc_relative */
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 */
634
HOWTO (R_860_LOPC, /* type */
636
2, /* size (0 = byte, 1 = short, 2 = long) */
638
TRUE, /* pc_relative */
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 */
648
HOWTO (R_860_HIGHADJ, /* type */
650
2, /* size (0 = byte, 1 = short, 2 = long) */
652
FALSE, /* pc_relative */
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 */
662
HOWTO (R_860_HAGOT, /* type */
664
2, /* size (0 = byte, 1 = short, 2 = long) */
666
FALSE, /* pc_relative */
668
complain_overflow_dont, /* complain_on_overflow */
669
bfd_elf_generic_reloc, /* special_function */
670
"R_860_HAGOT", /* name */
671
FALSE, /* partial_inplace */
673
0xffff, /* dst_mask */
674
TRUE), /* pcrel_offset */
676
HOWTO (R_860_HAGOTOFF, /* type */
678
2, /* size (0 = byte, 1 = short, 2 = long) */
680
FALSE, /* pc_relative */
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 */
690
HOWTO (R_860_HAPC, /* type */
692
2, /* size (0 = byte, 1 = short, 2 = long) */
694
TRUE, /* pc_relative */
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 */
704
HOWTO (R_860_HIGH, /* type */
706
2, /* size (0 = byte, 1 = short, 2 = long) */
708
FALSE, /* pc_relative */
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 */
718
HOWTO (R_860_HIGOT, /* type */
720
2, /* size (0 = byte, 1 = short, 2 = long) */
722
FALSE, /* pc_relative */
724
complain_overflow_dont, /* complain_on_overflow */
725
bfd_elf_generic_reloc, /* special_function */
726
"R_860_HIGOT", /* name */
727
FALSE, /* partial_inplace */
729
0xffff, /* dst_mask */
730
TRUE), /* pcrel_offset */
732
HOWTO (R_860_HIGOTOFF, /* type */
734
2, /* size (0 = byte, 1 = short, 2 = long) */
736
FALSE, /* pc_relative */
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 */
747
static unsigned char elf_code_to_howto_index[R_860_max + 1];
749
static reloc_howto_type *
750
lookup_howto (unsigned int rtype)
752
static int initialized = 0;
754
int howto_tbl_size = (int) (sizeof (elf32_i860_howto_table)
755
/ sizeof (elf32_i860_howto_table[0]));
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;
766
BFD_ASSERT (rtype <= R_860_max);
767
i = elf_code_to_howto_index[rtype];
768
if (i >= howto_tbl_size)
770
return elf32_i860_howto_table + i;
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)
788
case BFD_RELOC_860_COPY:
791
case BFD_RELOC_860_GLOB_DAT:
792
rtype = R_860_GLOB_DAT;
794
case BFD_RELOC_860_JUMP_SLOT:
795
rtype = R_860_JUMP_SLOT;
797
case BFD_RELOC_860_RELATIVE:
798
rtype = R_860_RELATIVE;
800
case BFD_RELOC_860_PC26:
803
case BFD_RELOC_860_PLT26:
806
case BFD_RELOC_860_PC16:
809
case BFD_RELOC_860_LOW0:
812
case BFD_RELOC_860_SPLIT0:
813
rtype = R_860_SPLIT0;
815
case BFD_RELOC_860_LOW1:
818
case BFD_RELOC_860_SPLIT1:
819
rtype = R_860_SPLIT1;
821
case BFD_RELOC_860_LOW2:
824
case BFD_RELOC_860_SPLIT2:
825
rtype = R_860_SPLIT2;
827
case BFD_RELOC_860_LOW3:
830
case BFD_RELOC_860_LOGOT0:
831
rtype = R_860_LOGOT0;
833
case BFD_RELOC_860_SPGOT0:
834
rtype = R_860_SPGOT0;
836
case BFD_RELOC_860_LOGOT1:
837
rtype = R_860_LOGOT1;
839
case BFD_RELOC_860_SPGOT1:
840
rtype = R_860_SPGOT1;
842
case BFD_RELOC_860_LOGOTOFF0:
843
rtype = R_860_LOGOTOFF0;
845
case BFD_RELOC_860_SPGOTOFF0:
846
rtype = R_860_SPGOTOFF0;
848
case BFD_RELOC_860_LOGOTOFF1:
849
rtype = R_860_LOGOTOFF1;
851
case BFD_RELOC_860_SPGOTOFF1:
852
rtype = R_860_SPGOTOFF1;
854
case BFD_RELOC_860_LOGOTOFF2:
855
rtype = R_860_LOGOTOFF2;
857
case BFD_RELOC_860_LOGOTOFF3:
858
rtype = R_860_LOGOTOFF3;
860
case BFD_RELOC_860_LOPC:
863
case BFD_RELOC_860_HIGHADJ:
864
rtype = R_860_HIGHADJ;
866
case BFD_RELOC_860_HAGOT:
869
case BFD_RELOC_860_HAGOTOFF:
870
rtype = R_860_HAGOTOFF;
872
case BFD_RELOC_860_HAPC:
875
case BFD_RELOC_860_HIGH:
878
case BFD_RELOC_860_HIGOT:
881
case BFD_RELOC_860_HIGOTOFF:
882
rtype = R_860_HIGOTOFF;
888
return lookup_howto (rtype);
891
static reloc_howto_type *
892
elf32_i860_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
898
i < (sizeof (elf32_i860_howto_table)
899
/ sizeof (elf32_i860_howto_table[0]));
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];
908
/* Given a ELF reloc, return the matching HOWTO structure. */
910
elf32_i860_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
912
Elf_Internal_Rela *elf_reloc)
915
= lookup_howto ((unsigned) ELF32_R_TYPE (elf_reloc->r_info));
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,
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);
932
value += rello->r_addend;
934
/* Separate the fields and insert. */
935
value = (((value & 0xf800) << 5) | (value & 0x7ff)) & howto->dst_mask;
936
insn = (insn & ~howto->dst_mask) | value;
938
bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
942
/* Specialized relocation handler for R_860_PC16. This relocation
943
involves a 16-bit, PC-relative field that is split into two contiguous
945
static bfd_reloc_status_type
946
elf32_i860_relocate_pc16 (bfd *input_bfd,
947
asection *input_section,
948
Elf_Internal_Rela *rello,
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);
957
/* Adjust for PC-relative relocation. */
958
value -= (input_section->output_section->vma
959
+ input_section->output_offset);
960
value -= rello->r_offset;
963
value += rello->r_addend;
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;
970
bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
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,
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);
989
/* Adjust for PC-relative relocation. */
990
value -= (input_section->output_section->vma
991
+ input_section->output_offset);
992
value -= rello->r_offset;
995
value += rello->r_addend;
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;
1001
bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
1002
return bfd_reloc_ok;
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,
1015
insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
1017
value += rel->r_addend;
1019
value = ((value >> 16) & 0xffff);
1021
insn = (insn & 0xffff0000) | value;
1023
bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
1024
return bfd_reloc_ok;
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,
1032
asection *input_section,
1034
Elf_Internal_Rela *rel,
1037
return _bfd_final_link_relocate (howto, input_bfd, input_section,
1038
contents, rel->r_offset, relocation,
1042
/* Relocate an i860 ELF section.
1044
This is boiler-plate code copied from fr30.
1046
The RELOCATE_SECTION function is called by the new ELF backend linker
1047
to handle the relocations for a section.
1049
The relocs are always passed as Rela structures; if the section
1050
actually uses Rel structures, the r_addend field will always be
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.
1057
This function does not have to worry about setting the reloc
1058
address or the reloc symbol index.
1060
LOCAL_SYMS is a pointer to the swapped in local symbols.
1062
LOCAL_SECTIONS is an array giving the section in the input file
1063
corresponding to the st_shndx field of each local symbol.
1065
The global hash table entry for the global symbols can be found
1066
via elf_sym_hashes (input_bfd).
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
1074
elf32_i860_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
1075
struct bfd_link_info *info,
1077
asection *input_section,
1079
Elf_Internal_Rela *relocs,
1080
Elf_Internal_Sym *local_syms,
1081
asection **local_sections)
1083
Elf_Internal_Shdr *symtab_hdr;
1084
struct elf_link_hash_entry **sym_hashes;
1085
Elf_Internal_Rela *rel;
1086
Elf_Internal_Rela *relend;
1088
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1089
sym_hashes = elf_sym_hashes (input_bfd);
1090
relend = relocs + input_section->reloc_count;
1092
for (rel = relocs; rel < relend; rel ++)
1094
reloc_howto_type * howto;
1095
unsigned long r_symndx;
1096
Elf_Internal_Sym * sym;
1098
struct elf_link_hash_entry * h;
1100
bfd_reloc_status_type r;
1101
const char * name = NULL;
1104
r_type = ELF32_R_TYPE (rel->r_info);
1105
r_symndx = ELF32_R_SYM (rel->r_info);
1107
howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
1112
if (r_symndx < symtab_hdr->sh_info)
1114
sym = local_syms + r_symndx;
1115
sec = local_sections [r_symndx];
1116
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
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;
1124
bfd_boolean unresolved_reloc, warned;
1126
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1127
r_symndx, symtab_hdr, sym_hashes,
1129
unresolved_reloc, warned);
1132
if (sec != NULL && discarded_section (sec))
1133
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
1134
rel, 1, relend, howto, 0, contents);
1136
if (info->relocatable)
1142
r = i860_final_link_relocate (howto, input_bfd, input_section,
1143
contents, rel, relocation);
1147
r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
1152
r = elf32_i860_relocate_pc16 (input_bfd, input_section, rel,
1153
contents, relocation);
1157
r = elf32_i860_relocate_pc26 (input_bfd, input_section, rel,
1158
contents, relocation);
1164
r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
1168
/* We do not yet handle GOT/PLT/Dynamic relocations. */
1170
case R_860_GLOB_DAT:
1171
case R_860_JUMP_SLOT:
1172
case R_860_RELATIVE:
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:
1186
case R_860_HAGOTOFF:
1189
case R_860_HIGOTOFF:
1190
r = bfd_reloc_notsupported;
1194
if (r != bfd_reloc_ok)
1196
const char * msg = (const char *) NULL;
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);
1206
case bfd_reloc_undefined:
1207
r = info->callbacks->undefined_symbol
1208
(info, name, input_bfd, input_section, rel->r_offset, TRUE);
1211
case bfd_reloc_outofrange:
1212
msg = _("internal error: out of range error");
1215
case bfd_reloc_notsupported:
1216
msg = _("internal error: unsupported relocation error");
1219
case bfd_reloc_dangerous:
1220
msg = _("internal error: dangerous relocation");
1224
msg = _("internal error: unknown error");
1229
r = info->callbacks->warning
1230
(info, msg, name, input_bfd, input_section, rel->r_offset);
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. */
1246
elf32_i860_is_local_label_name (bfd *abfd, const char *name)
1248
if (name[0] == '.' && name[1] == 'e' && name[2] == 'p' && name[3] == '.')
1251
return _bfd_elf_is_local_label_name (abfd, name);
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
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
1270
#include "elf32-target.h"