2003-09-14 Andrew Cagney <cagney@redhat.com>
[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 /* FIXME: This was copied from the i386 version originally but
466    appears to be wrong for i860.  For now we'll do nothing.  */
467 #if 0
468 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
469   {                                                             \
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));         \
474     else if (ptr)                                               \
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);   \
482     else                                                        \
483       cache_ptr->addend = 0;                                    \
484     if (ptr && howto_table[reloc.r_type].pc_relative)           \
485       cache_ptr->addend += asect->vma;                          \
486   }
487 #else
488 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)
489 #endif
490
491 /* We use the special COFF backend linker.  */
492 #define coff_relocate_section _bfd_coff_generic_relocate_section
493
494 static reloc_howto_type *
495 coff_i860_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
496                           asection *sec,
497                           struct internal_reloc *rel,
498                           struct coff_link_hash_entry *h,
499                           struct internal_syment *sym,
500                           bfd_vma *addendp)
501 {
502
503   reloc_howto_type *howto;
504
505   if (rel->r_type > sizeof (howto_table) / sizeof (howto_table[0]))
506     {
507       bfd_set_error (bfd_error_bad_value);
508       return NULL;
509     }
510
511   howto = howto_table + rel->r_type;
512
513   if (howto->pc_relative)
514     *addendp += sec->vma;
515
516   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
517     {
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
522          correct result.  */
523
524       BFD_ASSERT (h != NULL);
525
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;
533     }
534
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
537      common symbol.  */
538   if (h != NULL && h->root.type == bfd_link_hash_common)
539     *addendp += h->root.u.c.size;
540
541   return howto;
542 }
543
544 static reloc_howto_type *
545 coff_i860_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
546                              bfd_reloc_code_real_type code)
547 {
548   switch (code)
549     {
550     case BFD_RELOC_32:
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;
575     default:
576       BFD_FAIL ();
577       return 0;
578     }
579 }
580
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.  */
584
585 static void
586 i860_reloc_processing (arelent *cache_ptr, struct internal_reloc *dst,
587                        asymbol **symbols, bfd *abfd, asection *asect)
588 {
589   if (dst->r_type == COFF860_R_PAIR)
590     {
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;
596     }
597   else
598     {
599       /* For every other relocation, do exactly what coff_slurp_reloc_table
600          would do (which this code is taken directly from).  */
601       asymbol *ptr = NULL;
602       cache_ptr->address = dst->r_vaddr;
603
604       if (dst->r_symndx != -1)
605         {
606           if (dst->r_symndx < 0 || dst->r_symndx >= obj_conv_table_size (abfd))
607             {
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;
612               ptr = NULL;
613             }
614           else
615             {
616               cache_ptr->sym_ptr_ptr = (symbols
617                                         + obj_convert (abfd)[dst->r_symndx]);
618               ptr = *(cache_ptr->sym_ptr_ptr);
619             }
620         }
621       else
622         {
623           cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
624           ptr = NULL;
625         }
626
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.
631
632          Note that symbols which used to be common must be left alone.  */
633
634       /* Calculate any reloc addend by looking at the symbol.  */
635       CALC_ADDEND (abfd, ptr, (*dst), cache_ptr);
636
637       cache_ptr->address -= asect->vma;
638
639       /* Fill in the cache_ptr->howto field from dst->r_type.  */
640       RTYPE2HOWTO (cache_ptr, dst);
641     }
642 }
643 \f
644 #define coff_rtype_to_howto             coff_i860_rtype_to_howto
645 #define coff_bfd_reloc_type_lookup      coff_i860_reloc_type_lookup
646
647 #define RELOC_PROCESSING(relent, reloc, symbols, abfd, section) \
648   i860_reloc_processing (relent, reloc, symbols, abfd, section)
649
650 #include "coffcode.h"
651
652 static const bfd_target *
653 i3coff_object_p(bfd *a)
654 {
655   return coff_object_p (a);
656 }
657
658 const bfd_target
659 #ifdef TARGET_SYM
660   TARGET_SYM =
661 #else
662   i860coff_vec =
663 #endif
664 {
665 #ifdef TARGET_NAME
666   TARGET_NAME,
667 #else
668   "coff-i860",                  /* name */
669 #endif
670   bfd_target_coff_flavour,
671   BFD_ENDIAN_LITTLE,            /* data byte order is little */
672   BFD_ENDIAN_LITTLE,            /* header byte order is little */
673
674   (HAS_RELOC | EXEC_P |         /* object flags */
675    HAS_LINENO | HAS_DEBUG |
676    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
677
678   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
679   '_',                          /* leading underscore */
680   '/',                          /* ar_pad_char */
681   15,                           /* ar_max_namelen */
682
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 */
689
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 */
694        bfd_false},
695     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
696        _bfd_write_archive_contents, bfd_false},
697
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),
707
708   NULL,
709
710   COFF_SWAP_TABLE
711 };