2003-08-23 Jason Eckhardt <jle@rice.edu>
[external/binutils.git] / bfd / coff-i860.c
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
6
7 This file is part of BFD, the Binary File Descriptor library.
8
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.
13
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.
18
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.  */
22
23 #include "bfd.h"
24 #include "sysdep.h"
25 #include "libbfd.h"
26
27 #include "coff/i860.h"
28
29 #include "coff/internal.h"
30
31 #include "libcoff.h"
32
33
34 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
35 /* The page size is a guess based on ELF.  */
36
37 #define COFF_PAGE_SIZE 0x1000
38
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.  */
42
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.  */
47
48 static bfd_reloc_status_type
49 coff_i860_reloc (bfd *abfd,
50                  arelent *reloc_entry,
51                  asymbol *symbol,
52                  void *data,
53                  asection *input_section ATTRIBUTE_UNUSED,
54                  bfd *output_bfd,
55                  char **error_message ATTRIBUTE_UNUSED)
56 {
57   symvalue diff;
58
59   if (output_bfd == (bfd *) NULL)
60     return bfd_reloc_continue;
61
62   if (bfd_is_com_section (symbol->section))
63     {
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;
76     }
77   else
78     {
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;
84     }
85
86 #define DOIT(x) \
87   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
88
89     if (diff != 0)
90       {
91         reloc_howto_type *howto = reloc_entry->howto;
92         unsigned char *addr = (unsigned char *) data + reloc_entry->address;
93
94         switch (howto->size)
95           {
96           case 0:
97             {
98               char x = bfd_get_8 (abfd, addr);
99               DOIT (x);
100               bfd_put_8 (abfd, x, addr);
101             }
102             break;
103
104           case 1:
105             {
106               short x = bfd_get_16 (abfd, addr);
107               DOIT (x);
108               bfd_put_16 (abfd, (bfd_vma) x, addr);
109             }
110             break;
111
112           case 2:
113             {
114               long x = bfd_get_32 (abfd, addr);
115               DOIT (x);
116               bfd_put_32 (abfd, (bfd_vma) x, addr);
117             }
118             break;
119
120           default:
121             abort ();
122           }
123       }
124
125   /* Now let bfd_perform_relocation finish everything up.  */
126   return bfd_reloc_continue;
127 }
128
129 /* This is just a temporary measure until we teach bfd to generate 
130    these relocations.  */
131
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)
140 {
141   reloc_howto_type *howto = reloc_entry->howto;
142   fprintf (stderr, _("Relocation `%s' not yet implemented\n"), howto->name);
143 }
144
145 #ifndef PCRELOFFSET
146 #define PCRELOFFSET FALSE
147 #endif
148
149 static reloc_howto_type howto_table[] =
150 {
151   EMPTY_HOWTO (0),
152   EMPTY_HOWTO (1),
153   EMPTY_HOWTO (2),
154   EMPTY_HOWTO (3),
155   EMPTY_HOWTO (4),
156   EMPTY_HOWTO (5),
157   HOWTO (R_DIR32,               /* type */
158          0,                     /* rightshift */
159          2,                     /* size (0 = byte, 1 = short, 2 = long) */
160          32,                    /* bitsize */
161          FALSE,                 /* pc_relative */
162          0,                     /* bitpos */
163          complain_overflow_bitfield, /* complain_on_overflow */
164          coff_i860_reloc,       /* special_function */
165          "dir32",               /* name */
166          TRUE,                  /* partial_inplace */
167          0xffffffff,            /* src_mask */
168          0xffffffff,            /* dst_mask */
169          TRUE),                /* pcrel_offset */
170   /* {7}, */
171   HOWTO (R_IMAGEBASE,            /* type */
172          0,                     /* rightshift */
173          2,                     /* size (0 = byte, 1 = short, 2 = long) */
174          32,                    /* bitsize */
175          FALSE,                 /* pc_relative */
176          0,                     /* bitpos */
177          complain_overflow_bitfield, /* complain_on_overflow */
178          coff_i860_reloc,       /* special_function */
179          "rva32",                  /* name */
180          TRUE,                  /* partial_inplace */
181          0xffffffff,            /* src_mask */
182          0xffffffff,            /* dst_mask */
183          FALSE),                /* pcrel_offset */
184   EMPTY_HOWTO (010),
185   EMPTY_HOWTO (011),
186   EMPTY_HOWTO (012),
187   EMPTY_HOWTO (013),
188   EMPTY_HOWTO (014),
189   EMPTY_HOWTO (015),
190   EMPTY_HOWTO (016),
191   HOWTO (R_RELBYTE,             /* type */
192          0,                     /* rightshift */
193          0,                     /* size (0 = byte, 1 = short, 2 = long) */
194          8,                     /* bitsize */
195          FALSE,                 /* pc_relative */
196          0,                     /* bitpos */
197          complain_overflow_bitfield, /* complain_on_overflow */
198          coff_i860_reloc,       /* special_function */
199          "8",                   /* name */
200          TRUE,                  /* partial_inplace */
201          0x000000ff,            /* src_mask */
202          0x000000ff,            /* dst_mask */
203          PCRELOFFSET),          /* pcrel_offset */
204   HOWTO (R_RELWORD,             /* type */
205          0,                     /* rightshift */
206          1,                     /* size (0 = byte, 1 = short, 2 = long) */
207          16,                    /* bitsize */
208          FALSE,                 /* pc_relative */
209          0,                     /* bitpos */
210          complain_overflow_bitfield, /* complain_on_overflow */
211          coff_i860_reloc,       /* special_function */
212          "16",                  /* name */
213          TRUE,                  /* partial_inplace */
214          0x0000ffff,            /* src_mask */
215          0x0000ffff,            /* dst_mask */
216          PCRELOFFSET),          /* pcrel_offset */
217   HOWTO (R_RELLONG,             /* type */
218          0,                     /* rightshift */
219          2,                     /* size (0 = byte, 1 = short, 2 = long) */
220          32,                    /* bitsize */
221          FALSE,                 /* pc_relative */
222          0,                     /* bitpos */
223          complain_overflow_bitfield, /* complain_on_overflow */
224          coff_i860_reloc,       /* special_function */
225          "32",                  /* name */
226          TRUE,                  /* partial_inplace */
227          0xffffffff,            /* src_mask */
228          0xffffffff,            /* dst_mask */
229          PCRELOFFSET),          /* pcrel_offset */
230   HOWTO (R_PCRBYTE,             /* type */
231          0,                     /* rightshift */
232          0,                     /* size (0 = byte, 1 = short, 2 = long) */
233          8,                     /* bitsize */
234          TRUE,                  /* pc_relative */
235          0,                     /* bitpos */
236          complain_overflow_signed, /* complain_on_overflow */
237          coff_i860_reloc,       /* special_function */
238          "DISP8",               /* name */
239          TRUE,                  /* partial_inplace */
240          0x000000ff,            /* src_mask */
241          0x000000ff,            /* dst_mask */
242          PCRELOFFSET),          /* pcrel_offset */
243   HOWTO (R_PCRWORD,             /* type */
244          0,                     /* rightshift */
245          1,                     /* size (0 = byte, 1 = short, 2 = long) */
246          16,                    /* bitsize */
247          TRUE,                  /* pc_relative */
248          0,                     /* bitpos */
249          complain_overflow_signed, /* complain_on_overflow */
250          coff_i860_reloc,       /* special_function */
251          "DISP16",              /* name */
252          TRUE,                  /* partial_inplace */
253          0x0000ffff,            /* src_mask */
254          0x0000ffff,            /* dst_mask */
255          PCRELOFFSET),          /* pcrel_offset */
256   HOWTO (R_PCRLONG,             /* type */
257          0,                     /* rightshift */
258          2,                     /* size (0 = byte, 1 = short, 2 = long) */
259          32,                    /* bitsize */
260          TRUE,                  /* pc_relative */
261          0,                     /* bitpos */
262          complain_overflow_signed, /* complain_on_overflow */
263          coff_i860_reloc,       /* special_function */
264          "DISP32",              /* name */
265          TRUE,                  /* partial_inplace */
266          0xffffffff,            /* src_mask */
267          0xffffffff,            /* dst_mask */
268          PCRELOFFSET),          /* pcrel_offset */
269   EMPTY_HOWTO (0x15),
270   EMPTY_HOWTO (0x16),
271   EMPTY_HOWTO (0x17),
272   EMPTY_HOWTO (0x18),
273   EMPTY_HOWTO (0x19),
274   EMPTY_HOWTO (0x1a),
275   EMPTY_HOWTO (0x1b),
276   HOWTO (COFF860_R_PAIR,        /* type */
277          0,                     /* rightshift */
278          2,                     /* size (0 = byte, 1 = short, 2 = long) */
279          16,                    /* bitsize */
280          FALSE,                 /* pc_relative */
281          0,                     /* bitpos */
282          complain_overflow_dont, /* complain_on_overflow */
283          coff_i860_reloc_nyi,   /* special_function */
284          "PAIR",                /* name */
285          FALSE,                 /* partial_inplace */
286          0xffff,                /* src_mask */
287          0xffff,                /* dst_mask */
288          FALSE),                /* pcrel_offset */
289   EMPTY_HOWTO (0x1d),
290   HOWTO (COFF860_R_HIGH,        /* type */
291          16,                    /* rightshift */
292          2,                     /* size (0 = byte, 1 = short, 2 = long) */
293          16,                    /* bitsize */
294          FALSE,                 /* pc_relative */
295          0,                     /* bitpos */
296          complain_overflow_dont, /* complain_on_overflow */
297          coff_i860_reloc,       /* special_function */
298          "HIGH",                /* name */
299          FALSE,                 /* partial_inplace */
300          0xffff,                /* src_mask */
301          0xffff,                /* dst_mask */
302          FALSE),                /* pcrel_offset */
303   HOWTO (COFF860_R_LOW0,        /* type */
304          0,                     /* rightshift */
305          2,                     /* size (0 = byte, 1 = short, 2 = long) */
306          16,                    /* bitsize */
307          FALSE,                 /* pc_relative */
308          0,                     /* bitpos */
309          complain_overflow_dont, /* complain_on_overflow */
310          coff_i860_reloc,       /* special_function */
311          "LOW0",                /* name */
312          FALSE,                 /* partial_inplace */
313          0xffff,                /* src_mask */
314          0xffff,                /* dst_mask */
315          FALSE),                /* pcrel_offset */
316   HOWTO (COFF860_R_LOW1,        /* type */
317          0,                     /* rightshift */
318          2,                     /* size (0 = byte, 1 = short, 2 = long) */
319          16,                    /* bitsize */
320          FALSE,                 /* pc_relative */
321          0,                     /* bitpos */
322          complain_overflow_dont, /* complain_on_overflow */
323          coff_i860_reloc,       /* special_function */
324          "LOW1",                /* name */
325          FALSE,                 /* partial_inplace */
326          0xfffe,                /* src_mask */
327          0xfffe,                /* dst_mask */
328          FALSE),                /* pcrel_offset */
329   HOWTO (COFF860_R_LOW2,        /* type */
330          0,                     /* rightshift */
331          2,                     /* size (0 = byte, 1 = short, 2 = long) */
332          16,                    /* bitsize */
333          FALSE,                 /* pc_relative */
334          0,                     /* bitpos */
335          complain_overflow_dont, /* complain_on_overflow */
336          coff_i860_reloc,       /* special_function */
337          "LOW2",                /* name */
338          FALSE,                 /* partial_inplace */
339          0xfffc,                /* src_mask */
340          0xfffc,                /* dst_mask */
341          FALSE),                /* pcrel_offset */
342   HOWTO (COFF860_R_LOW3,        /* type */
343          0,                     /* rightshift */
344          2,                     /* size (0 = byte, 1 = short, 2 = long) */
345          16,                    /* bitsize */
346          FALSE,                 /* pc_relative */
347          0,                     /* bitpos */
348          complain_overflow_dont, /* complain_on_overflow */
349          coff_i860_reloc,       /* special_function */
350          "LOW3",                /* name */
351          FALSE,                 /* partial_inplace */
352          0xfff8,                /* src_mask */
353          0xfff8,                /* dst_mask */
354          FALSE),                /* pcrel_offset */
355   HOWTO (COFF860_R_LOW4,        /* type */
356          0,                     /* rightshift */
357          2,                     /* size (0 = byte, 1 = short, 2 = long) */
358          16,                    /* bitsize */
359          FALSE,                 /* pc_relative */
360          0,                     /* bitpos */
361          complain_overflow_dont, /* complain_on_overflow */
362          coff_i860_reloc,       /* special_function */
363          "LOW4",                /* name */
364          FALSE,                 /* partial_inplace */
365          0xfff0,                /* src_mask */
366          0xfff0,                /* dst_mask */
367          FALSE),                /* pcrel_offset */
368   HOWTO (COFF860_R_SPLIT0,      /* type */
369          0,                     /* rightshift */
370          2,                     /* size (0 = byte, 1 = short, 2 = long) */
371          16,                    /* bitsize */
372          FALSE,                 /* pc_relative */
373          0,                     /* bitpos */
374          complain_overflow_dont, /* complain_on_overflow */
375          coff_i860_reloc_nyi,   /* special_function */
376          "SPLIT0",              /* name */
377          FALSE,                 /* partial_inplace */
378          0x1f07ff,              /* src_mask */
379          0x1f07ff,              /* dst_mask */
380          FALSE),                /* pcrel_offset */
381   HOWTO (COFF860_R_SPLIT1,      /* type */
382          0,                     /* rightshift */
383          2,                     /* size (0 = byte, 1 = short, 2 = long) */
384          16,                    /* bitsize */
385          FALSE,                 /* pc_relative */
386          0,                     /* bitpos */
387          complain_overflow_dont, /* complain_on_overflow */
388          coff_i860_reloc_nyi,   /* special_function */
389          "SPLIT1",              /* name */
390          FALSE,                 /* partial_inplace */
391          0x1f07fe,              /* src_mask */
392          0x1f07fe,              /* dst_mask */
393          FALSE),                /* pcrel_offset */
394   HOWTO (COFF860_R_SPLIT2,      /* type */
395          0,                     /* rightshift */
396          2,                     /* size (0 = byte, 1 = short, 2 = long) */
397          16,                    /* bitsize */
398          FALSE,                 /* pc_relative */
399          0,                     /* bitpos */
400          complain_overflow_dont, /* complain_on_overflow */
401          coff_i860_reloc_nyi,   /* special_function */
402          "SPLIT2",              /* name */
403          FALSE,                 /* partial_inplace */
404          0x1f07fc,              /* src_mask */
405          0x1f07fc,              /* dst_mask */
406          FALSE),                /* pcrel_offset */
407   HOWTO (COFF860_R_HIGHADJ,     /* type */
408          0,                     /* rightshift */
409          2,                     /* size (0 = byte, 1 = short, 2 = long) */
410          16,                    /* bitsize */
411          FALSE,                 /* pc_relative */
412          0,                     /* bitpos */
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 */
421          2,                     /* rightshift */
422          2,                     /* size (0 = byte, 1 = short, 2 = long) */
423          26,                    /* bitsize */
424          TRUE,                  /* pc_relative */
425          0,                     /* bitpos */
426          complain_overflow_bitfield, /* complain_on_overflow */
427          coff_i860_reloc_nyi,   /* special_function */
428          "BRADDR",              /* name */
429          FALSE,                 /* partial_inplace */
430          0x3ffffff,             /* src_mask */
431          0x3ffffff,             /* dst_mask */
432          TRUE)                  /* pcrel_offset */
433 };
434
435 /* Turn a howto into a reloc number.  */
436
437 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
438 #define BADMAG(x) I860BADMAG(x)
439 #define I860 1                  /* Customize coffcode.h */
440
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                                       \
445     : NULL))
446
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
449    STYP_NOLOAD.  */
450 #define BSS_NOLOAD_IS_SHARED_LIBRARY
451
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
461    PC relative relocs.
462    FIXME: This macro refers to symbols and asect; these are from the
463    calling function, not the macro arguments.  */
464
465 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
466   {                                                             \
467     coff_symbol_type *coffsym = (coff_symbol_type *) NULL;      \
468     if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
469       coffsym = (obj_symbols (abfd)                             \
470                  + (cache_ptr->sym_ptr_ptr - symbols));         \
471     else if (ptr)                                               \
472       coffsym = coff_symbol_from (abfd, ptr);                   \
473     if (coffsym != (coff_symbol_type *) NULL                    \
474         && coffsym->native->u.syment.n_scnum == 0)              \
475       cache_ptr->addend = - coffsym->native->u.syment.n_value;  \
476     else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
477              && ptr->section != (asection *) NULL)              \
478       cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
479     else                                                        \
480       cache_ptr->addend = 0;                                    \
481     if (ptr && howto_table[reloc.r_type].pc_relative)           \
482       cache_ptr->addend += asect->vma;                          \
483   }
484
485 /* We use the special COFF backend linker.  */
486 #define coff_relocate_section _bfd_coff_generic_relocate_section
487
488 static reloc_howto_type *
489 coff_i860_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
490                           asection *sec,
491                           struct internal_reloc *rel,
492                           struct coff_link_hash_entry *h,
493                           struct internal_syment *sym,
494                           bfd_vma *addendp)
495 {
496
497   reloc_howto_type *howto;
498
499   if (rel->r_type > sizeof (howto_table) / sizeof (howto_table[0]))
500     {
501       bfd_set_error (bfd_error_bad_value);
502       return NULL;
503     }
504
505   howto = howto_table + rel->r_type;
506
507   if (howto->pc_relative)
508     *addendp += sec->vma;
509
510   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
511     {
512       /* This is a common symbol.  The section contents include the
513          size (sym->n_value) as an addend.  The relocate_section
514          function will be adding in the final value of the symbol.  We
515          need to subtract out the current size in order to get the
516          correct result.  */
517
518       BFD_ASSERT (h != NULL);
519
520       /* I think we *do* want to bypass this.  If we don't, I have seen some data
521          parameters get the wrong relcation address.  If I link two versions
522          with and without this section bypassed and then do a binary comparison,
523          the addresses which are different can be looked up in the map.  The
524          case in which this section has been bypassed has addresses which correspond
525          to values I can find in the map.  */
526       *addendp -= sym->n_value;
527     }
528
529   /* If the output symbol is common (in which case this must be a
530      relocatable link), we need to add in the final size of the
531      common symbol.  */
532   if (h != NULL && h->root.type == bfd_link_hash_common)
533     *addendp += h->root.u.c.size;
534
535   return howto;
536 }
537
538 static reloc_howto_type *
539 coff_i860_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
540                              bfd_reloc_code_real_type code)
541 {
542   switch (code)
543     {
544     case BFD_RELOC_32:
545       return howto_table + R_DIR32;
546     case BFD_RELOC_860_PC26:
547       return howto_table + COFF860_R_BRADDR;
548     case BFD_RELOC_860_PC16:
549       /* ??? How to handle PC16 for COFF?  SPLIT0 is close for now.  */
550       return howto_table + COFF860_R_SPLIT0;
551     case BFD_RELOC_860_LOW0:
552       return howto_table + COFF860_R_LOW0;
553     case BFD_RELOC_860_SPLIT0:
554       return howto_table + COFF860_R_SPLIT0;
555     case BFD_RELOC_860_LOW1:
556       return howto_table + COFF860_R_LOW1;
557     case BFD_RELOC_860_SPLIT1:
558       return howto_table + COFF860_R_SPLIT1;
559     case BFD_RELOC_860_LOW2:
560       return howto_table + COFF860_R_LOW2;
561     case BFD_RELOC_860_SPLIT2:
562       return howto_table + COFF860_R_SPLIT2;
563     case BFD_RELOC_860_LOW3:
564       return howto_table + COFF860_R_LOW3;
565     case BFD_RELOC_860_HIGHADJ:
566       return howto_table + COFF860_R_HIGHADJ;
567     case BFD_RELOC_860_HIGH:
568       return howto_table + COFF860_R_HIGH;
569     default:
570       BFD_FAIL ();
571       return 0;
572     }
573 }
574
575 /* This is called from coff_slurp_reloc_table for each relocation
576    entry.  This special handling is due to the `PAIR' relocation
577    which has a different meaning for the `r_symndx' field.  */
578
579 static void
580 i860_reloc_processing (arelent *cache_ptr, struct internal_reloc *dst,
581                        asymbol **symbols, bfd *abfd, asection *asect)
582 {
583   if (dst->r_type == COFF860_R_PAIR)
584     {
585       /* Handle the PAIR relocation specially.  */
586       cache_ptr->howto = howto_table + dst->r_type;
587       cache_ptr->address = dst->r_vaddr;
588       cache_ptr->addend = dst->r_symndx;
589       cache_ptr->sym_ptr_ptr= bfd_abs_section_ptr->symbol_ptr_ptr;
590     }
591   else
592     {
593       /* For every other relocation, do exactly what coff_slurp_reloc_table
594          would do (which this code is taken directly from).  */
595       asymbol *ptr = NULL;
596       cache_ptr->address = dst->r_vaddr;
597
598       if (dst->r_symndx != -1)
599         {
600           if (dst->r_symndx < 0 || dst->r_symndx >= obj_conv_table_size (abfd))
601             {
602               (*_bfd_error_handler)
603                 (_("%s: warning: illegal symbol index %ld in relocs"),
604                  bfd_archive_filename (abfd), dst->r_symndx);
605               cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
606               ptr = NULL;
607             }
608           else
609             {
610               cache_ptr->sym_ptr_ptr = (symbols
611                                         + obj_convert (abfd)[dst->r_symndx]);
612               ptr = *(cache_ptr->sym_ptr_ptr);
613             }
614         }
615       else
616         {
617           cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
618           ptr = NULL;
619         }
620
621       /* The symbols definitions that we have read in have been
622          relocated as if their sections started at 0. But the offsets
623          refering to the symbols in the raw data have not been
624          modified, so we have to have a negative addend to compensate.
625
626          Note that symbols which used to be common must be left alone.  */
627
628       /* Calculate any reloc addend by looking at the symbol.  */
629       CALC_ADDEND (abfd, ptr, (*dst), cache_ptr);
630
631       cache_ptr->address -= asect->vma;
632
633       /* Fill in the cache_ptr->howto field from dst->r_type.  */
634       RTYPE2HOWTO (cache_ptr, dst);
635     }
636 }
637 \f
638 #define coff_rtype_to_howto             coff_i860_rtype_to_howto
639 #define coff_bfd_reloc_type_lookup      coff_i860_reloc_type_lookup
640
641 #define RELOC_PROCESSING(relent, reloc, symbols, abfd, section) \
642   i860_reloc_processing (relent, reloc, symbols, abfd, section)
643
644 #include "coffcode.h"
645
646 static const bfd_target *
647 i3coff_object_p(bfd *a)
648 {
649   return coff_object_p (a);
650 }
651
652 const bfd_target
653 #ifdef TARGET_SYM
654   TARGET_SYM =
655 #else
656   i860coff_vec =
657 #endif
658 {
659 #ifdef TARGET_NAME
660   TARGET_NAME,
661 #else
662   "coff-i860",                  /* name */
663 #endif
664   bfd_target_coff_flavour,
665   BFD_ENDIAN_LITTLE,            /* data byte order is little */
666   BFD_ENDIAN_LITTLE,            /* header byte order is little */
667
668   (HAS_RELOC | EXEC_P |         /* object flags */
669    HAS_LINENO | HAS_DEBUG |
670    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
671
672   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
673   '_',                          /* leading underscore */
674   '/',                          /* ar_pad_char */
675   15,                           /* ar_max_namelen */
676
677   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
678      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
679      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
680   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
681      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
682      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
683
684 /* Note that we allow an object file to be treated as a core file as well.  */
685     {_bfd_dummy_target, i3coff_object_p, /* bfd_check_format */
686        bfd_generic_archive_p, i3coff_object_p},
687     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
688        bfd_false},
689     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
690        _bfd_write_archive_contents, bfd_false},
691
692      BFD_JUMP_TABLE_GENERIC (coff),
693      BFD_JUMP_TABLE_COPY (coff),
694      BFD_JUMP_TABLE_CORE (_bfd_nocore),
695      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
696      BFD_JUMP_TABLE_SYMBOLS (coff),
697      BFD_JUMP_TABLE_RELOCS (coff),
698      BFD_JUMP_TABLE_WRITE (coff),
699      BFD_JUMP_TABLE_LINK (coff),
700      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
701
702   NULL,
703
704   COFF_SWAP_TABLE
705 };