1
/* BFD back-end for Intel i860 COFF files.
2
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002, 2003
3
Free Software Foundation, Inc.
4
Created mostly by substituting "860" for "386" in coff-i386.c
5
Harry Dolan <dolan@ssd.intel.com>, October 1995
7
This file is part of BFD, the Binary File Descriptor library.
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2 of the License, or
12
(at your option) any later version.
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
GNU General Public License for more details.
19
You should have received a copy of the GNU General Public License
20
along with this program; if not, write to the Free Software
21
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
27
#include "coff/i860.h"
29
#include "coff/internal.h"
34
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
35
/* The page size is a guess based on ELF. */
37
#define COFF_PAGE_SIZE 0x1000
39
/* For some reason when using i860 COFF the value stored in the .text
40
section for a reference to a common symbol is the value itself plus
41
any desired offset. Ian Taylor, Cygnus Support. */
43
/* If we are producing relocatable output, we need to do some
44
adjustments to the object file that are not done by the
45
bfd_perform_relocation function. This function is called by every
46
reloc type to make any required adjustments. */
48
static bfd_reloc_status_type
49
coff_i860_reloc (bfd *abfd,
53
asection *input_section ATTRIBUTE_UNUSED,
55
char **error_message ATTRIBUTE_UNUSED)
59
if (output_bfd == (bfd *) NULL)
60
return bfd_reloc_continue;
62
if (bfd_is_com_section (symbol->section))
64
/* We are relocating a common symbol. The current value in the
65
object file is ORIG + OFFSET, where ORIG is the value of the
66
common symbol as seen by the object file when it was compiled
67
(this may be zero if the symbol was undefined) and OFFSET is
68
the offset into the common symbol (normally zero, but may be
69
non-zero when referring to a field in a common structure).
70
ORIG is the negative of reloc_entry->addend, which is set by
71
the CALC_ADDEND macro below. We want to replace the value in
72
the object file with NEW + OFFSET, where NEW is the value of
73
the common symbol which we are going to put in the final
74
object file. NEW is symbol->value. */
75
diff = symbol->value + reloc_entry->addend;
79
/* For some reason bfd_perform_relocation always effectively
80
ignores the addend for a COFF target when producing
81
relocatable output. This seems to be always wrong for 860
82
COFF, so we handle the addend here instead. */
83
diff = reloc_entry->addend;
87
x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
91
reloc_howto_type *howto = reloc_entry->howto;
92
unsigned char *addr = (unsigned char *) data + reloc_entry->address;
98
char x = bfd_get_8 (abfd, addr);
100
bfd_put_8 (abfd, x, addr);
106
short x = bfd_get_16 (abfd, addr);
108
bfd_put_16 (abfd, (bfd_vma) x, addr);
114
long x = bfd_get_32 (abfd, addr);
116
bfd_put_32 (abfd, (bfd_vma) x, addr);
125
/* Now let bfd_perform_relocation finish everything up. */
126
return bfd_reloc_continue;
129
/* This is just a temporary measure until we teach bfd to generate
130
these relocations. */
132
static bfd_reloc_status_type
133
coff_i860_reloc_nyi (bfd *abfd ATTRIBUTE_UNUSED,
134
arelent *reloc_entry,
135
asymbol *symbol ATTRIBUTE_UNUSED,
136
void *data ATTRIBUTE_UNUSED,
137
asection *input_section ATTRIBUTE_UNUSED,
138
bfd *output_bfd ATTRIBUTE_UNUSED,
139
char **error_message ATTRIBUTE_UNUSED)
141
reloc_howto_type *howto = reloc_entry->howto;
142
fprintf (stderr, _("Relocation `%s' not yet implemented\n"), howto->name);
146
#define PCRELOFFSET FALSE
149
static reloc_howto_type howto_table[] =
157
HOWTO (R_DIR32, /* type */
159
2, /* size (0 = byte, 1 = short, 2 = long) */
161
FALSE, /* pc_relative */
163
complain_overflow_bitfield, /* complain_on_overflow */
164
coff_i860_reloc, /* special_function */
166
TRUE, /* partial_inplace */
167
0xffffffff, /* src_mask */
168
0xffffffff, /* dst_mask */
169
TRUE), /* pcrel_offset */
171
HOWTO (R_IMAGEBASE, /* type */
173
2, /* size (0 = byte, 1 = short, 2 = long) */
175
FALSE, /* pc_relative */
177
complain_overflow_bitfield, /* complain_on_overflow */
178
coff_i860_reloc, /* special_function */
180
TRUE, /* partial_inplace */
181
0xffffffff, /* src_mask */
182
0xffffffff, /* dst_mask */
183
FALSE), /* pcrel_offset */
191
HOWTO (R_RELBYTE, /* type */
193
0, /* size (0 = byte, 1 = short, 2 = long) */
195
FALSE, /* pc_relative */
197
complain_overflow_bitfield, /* complain_on_overflow */
198
coff_i860_reloc, /* special_function */
200
TRUE, /* partial_inplace */
201
0x000000ff, /* src_mask */
202
0x000000ff, /* dst_mask */
203
PCRELOFFSET), /* pcrel_offset */
204
HOWTO (R_RELWORD, /* type */
206
1, /* size (0 = byte, 1 = short, 2 = long) */
208
FALSE, /* pc_relative */
210
complain_overflow_bitfield, /* complain_on_overflow */
211
coff_i860_reloc, /* special_function */
213
TRUE, /* partial_inplace */
214
0x0000ffff, /* src_mask */
215
0x0000ffff, /* dst_mask */
216
PCRELOFFSET), /* pcrel_offset */
217
HOWTO (R_RELLONG, /* type */
219
2, /* size (0 = byte, 1 = short, 2 = long) */
221
FALSE, /* pc_relative */
223
complain_overflow_bitfield, /* complain_on_overflow */
224
coff_i860_reloc, /* special_function */
226
TRUE, /* partial_inplace */
227
0xffffffff, /* src_mask */
228
0xffffffff, /* dst_mask */
229
PCRELOFFSET), /* pcrel_offset */
230
HOWTO (R_PCRBYTE, /* type */
232
0, /* size (0 = byte, 1 = short, 2 = long) */
234
TRUE, /* pc_relative */
236
complain_overflow_signed, /* complain_on_overflow */
237
coff_i860_reloc, /* special_function */
239
TRUE, /* partial_inplace */
240
0x000000ff, /* src_mask */
241
0x000000ff, /* dst_mask */
242
PCRELOFFSET), /* pcrel_offset */
243
HOWTO (R_PCRWORD, /* type */
245
1, /* size (0 = byte, 1 = short, 2 = long) */
247
TRUE, /* pc_relative */
249
complain_overflow_signed, /* complain_on_overflow */
250
coff_i860_reloc, /* special_function */
252
TRUE, /* partial_inplace */
253
0x0000ffff, /* src_mask */
254
0x0000ffff, /* dst_mask */
255
PCRELOFFSET), /* pcrel_offset */
256
HOWTO (R_PCRLONG, /* type */
258
2, /* size (0 = byte, 1 = short, 2 = long) */
260
TRUE, /* pc_relative */
262
complain_overflow_signed, /* complain_on_overflow */
263
coff_i860_reloc, /* special_function */
265
TRUE, /* partial_inplace */
266
0xffffffff, /* src_mask */
267
0xffffffff, /* dst_mask */
268
PCRELOFFSET), /* pcrel_offset */
276
HOWTO (COFF860_R_PAIR, /* type */
278
2, /* size (0 = byte, 1 = short, 2 = long) */
280
FALSE, /* pc_relative */
282
complain_overflow_dont, /* complain_on_overflow */
283
coff_i860_reloc_nyi, /* special_function */
285
FALSE, /* partial_inplace */
286
0xffff, /* src_mask */
287
0xffff, /* dst_mask */
288
FALSE), /* pcrel_offset */
290
HOWTO (COFF860_R_HIGH, /* type */
292
2, /* size (0 = byte, 1 = short, 2 = long) */
294
FALSE, /* pc_relative */
296
complain_overflow_dont, /* complain_on_overflow */
297
coff_i860_reloc, /* special_function */
299
FALSE, /* partial_inplace */
300
0xffff, /* src_mask */
301
0xffff, /* dst_mask */
302
FALSE), /* pcrel_offset */
303
HOWTO (COFF860_R_LOW0, /* type */
305
2, /* size (0 = byte, 1 = short, 2 = long) */
307
FALSE, /* pc_relative */
309
complain_overflow_dont, /* complain_on_overflow */
310
coff_i860_reloc, /* special_function */
312
FALSE, /* partial_inplace */
313
0xffff, /* src_mask */
314
0xffff, /* dst_mask */
315
FALSE), /* pcrel_offset */
316
HOWTO (COFF860_R_LOW1, /* type */
318
2, /* size (0 = byte, 1 = short, 2 = long) */
320
FALSE, /* pc_relative */
322
complain_overflow_dont, /* complain_on_overflow */
323
coff_i860_reloc, /* special_function */
325
FALSE, /* partial_inplace */
326
0xfffe, /* src_mask */
327
0xfffe, /* dst_mask */
328
FALSE), /* pcrel_offset */
329
HOWTO (COFF860_R_LOW2, /* type */
331
2, /* size (0 = byte, 1 = short, 2 = long) */
333
FALSE, /* pc_relative */
335
complain_overflow_dont, /* complain_on_overflow */
336
coff_i860_reloc, /* special_function */
338
FALSE, /* partial_inplace */
339
0xfffc, /* src_mask */
340
0xfffc, /* dst_mask */
341
FALSE), /* pcrel_offset */
342
HOWTO (COFF860_R_LOW3, /* type */
344
2, /* size (0 = byte, 1 = short, 2 = long) */
346
FALSE, /* pc_relative */
348
complain_overflow_dont, /* complain_on_overflow */
349
coff_i860_reloc, /* special_function */
351
FALSE, /* partial_inplace */
352
0xfff8, /* src_mask */
353
0xfff8, /* dst_mask */
354
FALSE), /* pcrel_offset */
355
HOWTO (COFF860_R_LOW4, /* type */
357
2, /* size (0 = byte, 1 = short, 2 = long) */
359
FALSE, /* pc_relative */
361
complain_overflow_dont, /* complain_on_overflow */
362
coff_i860_reloc, /* special_function */
364
FALSE, /* partial_inplace */
365
0xfff0, /* src_mask */
366
0xfff0, /* dst_mask */
367
FALSE), /* pcrel_offset */
368
HOWTO (COFF860_R_SPLIT0, /* type */
370
2, /* size (0 = byte, 1 = short, 2 = long) */
372
FALSE, /* pc_relative */
374
complain_overflow_dont, /* complain_on_overflow */
375
coff_i860_reloc_nyi, /* special_function */
377
FALSE, /* partial_inplace */
378
0x1f07ff, /* src_mask */
379
0x1f07ff, /* dst_mask */
380
FALSE), /* pcrel_offset */
381
HOWTO (COFF860_R_SPLIT1, /* type */
383
2, /* size (0 = byte, 1 = short, 2 = long) */
385
FALSE, /* pc_relative */
387
complain_overflow_dont, /* complain_on_overflow */
388
coff_i860_reloc_nyi, /* special_function */
390
FALSE, /* partial_inplace */
391
0x1f07fe, /* src_mask */
392
0x1f07fe, /* dst_mask */
393
FALSE), /* pcrel_offset */
394
HOWTO (COFF860_R_SPLIT2, /* type */
396
2, /* size (0 = byte, 1 = short, 2 = long) */
398
FALSE, /* pc_relative */
400
complain_overflow_dont, /* complain_on_overflow */
401
coff_i860_reloc_nyi, /* special_function */
403
FALSE, /* partial_inplace */
404
0x1f07fc, /* src_mask */
405
0x1f07fc, /* dst_mask */
406
FALSE), /* pcrel_offset */
407
HOWTO (COFF860_R_HIGHADJ, /* type */
409
2, /* size (0 = byte, 1 = short, 2 = long) */
411
FALSE, /* pc_relative */
413
complain_overflow_dont, /* complain_on_overflow */
414
coff_i860_reloc_nyi, /* special_function */
415
"HIGHADJ", /* name */
416
FALSE, /* partial_inplace */
417
0xffff, /* src_mask */
418
0xffff, /* dst_mask */
419
FALSE), /* pcrel_offset */
420
HOWTO (COFF860_R_BRADDR, /* type */
422
2, /* size (0 = byte, 1 = short, 2 = long) */
424
TRUE, /* pc_relative */
426
complain_overflow_bitfield, /* complain_on_overflow */
427
coff_i860_reloc_nyi, /* special_function */
429
FALSE, /* partial_inplace */
430
0x3ffffff, /* src_mask */
431
0x3ffffff, /* dst_mask */
432
TRUE) /* pcrel_offset */
435
/* Turn a howto into a reloc number. */
437
#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
438
#define BADMAG(x) I860BADMAG(x)
439
#define I860 1 /* Customize coffcode.h */
441
#define RTYPE2HOWTO(cache_ptr, dst) \
442
((cache_ptr)->howto = \
443
((dst)->r_type < sizeof (howto_table) / sizeof (howto_table[0]) \
444
? howto_table + (dst)->r_type \
447
/* For 860 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
448
library. On some other COFF targets STYP_BSS is normally
450
#define BSS_NOLOAD_IS_SHARED_LIBRARY
452
/* Compute the addend of a reloc. If the reloc is to a common symbol,
453
the object file contains the value of the common symbol. By the
454
time this is called, the linker may be using a different symbol
455
from a different object file with a different value. Therefore, we
456
hack wildly to locate the original symbol from this file so that we
457
can make the correct adjustment. This macro sets coffsym to the
458
symbol from the original file, and uses it to set the addend value
459
correctly. If this is not a common symbol, the usual addend
460
calculation is done, except that an additional tweak is needed for
462
FIXME: This macro refers to symbols and asect; these are from the
463
calling function, not the macro arguments. */
465
/* FIXME: This was copied from the i386 version originally but
466
appears to be wrong for i860. For now we'll do nothing. */
468
#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
470
coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
471
if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
472
coffsym = (obj_symbols (abfd) \
473
+ (cache_ptr->sym_ptr_ptr - symbols)); \
475
coffsym = coff_symbol_from (abfd, ptr); \
476
if (coffsym != (coff_symbol_type *) NULL \
477
&& coffsym->native->u.syment.n_scnum == 0) \
478
cache_ptr->addend = - coffsym->native->u.syment.n_value; \
479
else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
480
&& ptr->section != (asection *) NULL) \
481
cache_ptr->addend = - (ptr->section->vma + ptr->value); \
483
cache_ptr->addend = 0; \
484
if (ptr && howto_table[reloc.r_type].pc_relative) \
485
cache_ptr->addend += asect->vma; \
488
#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)
491
/* We use the special COFF backend linker. */
492
#define coff_relocate_section _bfd_coff_generic_relocate_section
494
static reloc_howto_type *
495
coff_i860_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
497
struct internal_reloc *rel,
498
struct coff_link_hash_entry *h,
499
struct internal_syment *sym,
503
reloc_howto_type *howto;
505
if (rel->r_type > sizeof (howto_table) / sizeof (howto_table[0]))
507
bfd_set_error (bfd_error_bad_value);
511
howto = howto_table + rel->r_type;
513
if (howto->pc_relative)
514
*addendp += sec->vma;
516
if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
518
/* This is a common symbol. The section contents include the
519
size (sym->n_value) as an addend. The relocate_section
520
function will be adding in the final value of the symbol. We
521
need to subtract out the current size in order to get the
524
BFD_ASSERT (h != NULL);
526
/* I think we *do* want to bypass this. If we don't, I have seen some data
527
parameters get the wrong relcation address. If I link two versions
528
with and without this section bypassed and then do a binary comparison,
529
the addresses which are different can be looked up in the map. The
530
case in which this section has been bypassed has addresses which correspond
531
to values I can find in the map. */
532
*addendp -= sym->n_value;
535
/* If the output symbol is common (in which case this must be a
536
relocatable link), we need to add in the final size of the
538
if (h != NULL && h->root.type == bfd_link_hash_common)
539
*addendp += h->root.u.c.size;
544
static reloc_howto_type *
545
coff_i860_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
546
bfd_reloc_code_real_type code)
551
return howto_table + R_DIR32;
552
case BFD_RELOC_860_PC26:
553
return howto_table + COFF860_R_BRADDR;
554
case BFD_RELOC_860_PC16:
555
/* ??? How to handle PC16 for COFF? SPLIT0 is close for now. */
556
return howto_table + COFF860_R_SPLIT0;
557
case BFD_RELOC_860_LOW0:
558
return howto_table + COFF860_R_LOW0;
559
case BFD_RELOC_860_SPLIT0:
560
return howto_table + COFF860_R_SPLIT0;
561
case BFD_RELOC_860_LOW1:
562
return howto_table + COFF860_R_LOW1;
563
case BFD_RELOC_860_SPLIT1:
564
return howto_table + COFF860_R_SPLIT1;
565
case BFD_RELOC_860_LOW2:
566
return howto_table + COFF860_R_LOW2;
567
case BFD_RELOC_860_SPLIT2:
568
return howto_table + COFF860_R_SPLIT2;
569
case BFD_RELOC_860_LOW3:
570
return howto_table + COFF860_R_LOW3;
571
case BFD_RELOC_860_HIGHADJ:
572
return howto_table + COFF860_R_HIGHADJ;
573
case BFD_RELOC_860_HIGH:
574
return howto_table + COFF860_R_HIGH;
581
/* This is called from coff_slurp_reloc_table for each relocation
582
entry. This special handling is due to the `PAIR' relocation
583
which has a different meaning for the `r_symndx' field. */
586
i860_reloc_processing (arelent *cache_ptr, struct internal_reloc *dst,
587
asymbol **symbols, bfd *abfd, asection *asect)
589
if (dst->r_type == COFF860_R_PAIR)
591
/* Handle the PAIR relocation specially. */
592
cache_ptr->howto = howto_table + dst->r_type;
593
cache_ptr->address = dst->r_vaddr;
594
cache_ptr->addend = dst->r_symndx;
595
cache_ptr->sym_ptr_ptr= bfd_abs_section_ptr->symbol_ptr_ptr;
599
/* For every other relocation, do exactly what coff_slurp_reloc_table
600
would do (which this code is taken directly from). */
602
cache_ptr->address = dst->r_vaddr;
604
if (dst->r_symndx != -1)
606
if (dst->r_symndx < 0 || dst->r_symndx >= obj_conv_table_size (abfd))
608
(*_bfd_error_handler)
609
(_("%s: warning: illegal symbol index %ld in relocs"),
610
bfd_archive_filename (abfd), dst->r_symndx);
611
cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
616
cache_ptr->sym_ptr_ptr = (symbols
617
+ obj_convert (abfd)[dst->r_symndx]);
618
ptr = *(cache_ptr->sym_ptr_ptr);
623
cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
627
/* The symbols definitions that we have read in have been
628
relocated as if their sections started at 0. But the offsets
629
refering to the symbols in the raw data have not been
630
modified, so we have to have a negative addend to compensate.
632
Note that symbols which used to be common must be left alone. */
634
/* Calculate any reloc addend by looking at the symbol. */
635
CALC_ADDEND (abfd, ptr, (*dst), cache_ptr);
637
cache_ptr->address -= asect->vma;
639
/* Fill in the cache_ptr->howto field from dst->r_type. */
640
RTYPE2HOWTO (cache_ptr, dst);
644
#define coff_rtype_to_howto coff_i860_rtype_to_howto
645
#define coff_bfd_reloc_type_lookup coff_i860_reloc_type_lookup
647
#define RELOC_PROCESSING(relent, reloc, symbols, abfd, section) \
648
i860_reloc_processing (relent, reloc, symbols, abfd, section)
650
#include "coffcode.h"
652
static const bfd_target *
653
i3coff_object_p(bfd *a)
655
return coff_object_p (a);
668
"coff-i860", /* name */
670
bfd_target_coff_flavour,
671
BFD_ENDIAN_LITTLE, /* data byte order is little */
672
BFD_ENDIAN_LITTLE, /* header byte order is little */
674
(HAS_RELOC | EXEC_P | /* object flags */
675
HAS_LINENO | HAS_DEBUG |
676
HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
678
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
679
'_', /* leading underscore */
680
'/', /* ar_pad_char */
681
15, /* ar_max_namelen */
683
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
684
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
685
bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
686
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
687
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
688
bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
690
/* Note that we allow an object file to be treated as a core file as well. */
691
{_bfd_dummy_target, i3coff_object_p, /* bfd_check_format */
692
bfd_generic_archive_p, i3coff_object_p},
693
{bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
695
{bfd_false, coff_write_object_contents, /* bfd_write_contents */
696
_bfd_write_archive_contents, bfd_false},
698
BFD_JUMP_TABLE_GENERIC (coff),
699
BFD_JUMP_TABLE_COPY (coff),
700
BFD_JUMP_TABLE_CORE (_bfd_nocore),
701
BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
702
BFD_JUMP_TABLE_SYMBOLS (coff),
703
BFD_JUMP_TABLE_RELOCS (coff),
704
BFD_JUMP_TABLE_WRITE (coff),
705
BFD_JUMP_TABLE_LINK (coff),
706
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),