Back to index

cell-binutils  2.17cvs20070401
coff-i860.c
Go to the documentation of this file.
00001 /* BFD back-end for Intel i860 COFF files.
00002    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002,
00003    2003, 2004, 2005, 2007 Free Software Foundation, Inc.
00004    Created mostly by substituting "860" for "386" in coff-i386.c
00005    Harry Dolan <dolan@ssd.intel.com>, October 1995
00006 
00007 This file is part of BFD, the Binary File Descriptor library.
00008 
00009 This program is free software; you can redistribute it and/or modify
00010 it under the terms of the GNU General Public License as published by
00011 the Free Software Foundation; either version 2 of the License, or
00012 (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00022 
00023 #include "bfd.h"
00024 #include "sysdep.h"
00025 #include "libbfd.h"
00026 
00027 #include "coff/i860.h"
00028 
00029 #include "coff/internal.h"
00030 
00031 #include "libcoff.h"
00032 
00033 
00034 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
00035 /* The page size is a guess based on ELF.  */
00036 
00037 #define COFF_PAGE_SIZE 0x1000
00038 
00039 /* For some reason when using i860 COFF the value stored in the .text
00040    section for a reference to a common symbol is the value itself plus
00041    any desired offset.  Ian Taylor, Cygnus Support.  */
00042 
00043 /* If we are producing relocatable output, we need to do some
00044    adjustments to the object file that are not done by the
00045    bfd_perform_relocation function.  This function is called by every
00046    reloc type to make any required adjustments.  */
00047 
00048 static bfd_reloc_status_type
00049 coff_i860_reloc (bfd *abfd,
00050                arelent *reloc_entry,
00051                asymbol *symbol,
00052                void *data,
00053                asection *input_section ATTRIBUTE_UNUSED,
00054                bfd *output_bfd,
00055                char **error_message ATTRIBUTE_UNUSED)
00056 {
00057   symvalue diff;
00058 
00059   if (output_bfd == (bfd *) NULL)
00060     return bfd_reloc_continue;
00061 
00062   if (bfd_is_com_section (symbol->section))
00063     {
00064       /* We are relocating a common symbol.  The current value in the
00065         object file is ORIG + OFFSET, where ORIG is the value of the
00066         common symbol as seen by the object file when it was compiled
00067         (this may be zero if the symbol was undefined) and OFFSET is
00068         the offset into the common symbol (normally zero, but may be
00069         non-zero when referring to a field in a common structure).
00070         ORIG is the negative of reloc_entry->addend, which is set by
00071         the CALC_ADDEND macro below.  We want to replace the value in
00072         the object file with NEW + OFFSET, where NEW is the value of
00073         the common symbol which we are going to put in the final
00074         object file.  NEW is symbol->value.  */
00075       diff = symbol->value + reloc_entry->addend;
00076     }
00077   else
00078     {
00079       /* For some reason bfd_perform_relocation always effectively
00080         ignores the addend for a COFF target when producing
00081         relocatable output.  This seems to be always wrong for 860
00082         COFF, so we handle the addend here instead.  */
00083       diff = reloc_entry->addend;
00084     }
00085 
00086 #define DOIT(x) \
00087   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
00088 
00089     if (diff != 0)
00090       {
00091        reloc_howto_type *howto = reloc_entry->howto;
00092        unsigned char *addr = (unsigned char *) data + reloc_entry->address;
00093 
00094        switch (howto->size)
00095          {
00096          case 0:
00097            {
00098              char x = bfd_get_8 (abfd, addr);
00099              DOIT (x);
00100              bfd_put_8 (abfd, x, addr);
00101            }
00102            break;
00103 
00104          case 1:
00105            {
00106              short x = bfd_get_16 (abfd, addr);
00107              DOIT (x);
00108              bfd_put_16 (abfd, (bfd_vma) x, addr);
00109            }
00110            break;
00111 
00112          case 2:
00113            {
00114              long x = bfd_get_32 (abfd, addr);
00115              DOIT (x);
00116              bfd_put_32 (abfd, (bfd_vma) x, addr);
00117            }
00118            break;
00119 
00120          default:
00121            abort ();
00122          }
00123       }
00124 
00125   /* Now let bfd_perform_relocation finish everything up.  */
00126   return bfd_reloc_continue;
00127 }
00128 
00129 /* This is just a temporary measure until we teach bfd to generate 
00130    these relocations.  */
00131 
00132 static bfd_reloc_status_type
00133 coff_i860_reloc_nyi (bfd *abfd ATTRIBUTE_UNUSED,
00134                    arelent *reloc_entry,
00135                    asymbol *symbol ATTRIBUTE_UNUSED,
00136                    void *data ATTRIBUTE_UNUSED,
00137                    asection *input_section ATTRIBUTE_UNUSED,
00138                    bfd *output_bfd ATTRIBUTE_UNUSED,
00139                    char **error_message ATTRIBUTE_UNUSED)
00140 {
00141   reloc_howto_type *howto = reloc_entry->howto;
00142   fprintf (stderr, _("Relocation `%s' not yet implemented\n"), howto->name);
00143   return bfd_reloc_notsupported;
00144 }
00145 
00146 #ifndef PCRELOFFSET
00147 #define PCRELOFFSET FALSE
00148 #endif
00149 
00150 static reloc_howto_type howto_table[] =
00151 {
00152   EMPTY_HOWTO (0),
00153   EMPTY_HOWTO (1),
00154   EMPTY_HOWTO (2),
00155   EMPTY_HOWTO (3),
00156   EMPTY_HOWTO (4),
00157   EMPTY_HOWTO (5),
00158   HOWTO (R_DIR32,               /* type */
00159         0,                    /* rightshift */
00160         2,                    /* size (0 = byte, 1 = short, 2 = long) */
00161         32,                   /* bitsize */
00162         FALSE,                       /* pc_relative */
00163         0,                    /* bitpos */
00164         complain_overflow_bitfield, /* complain_on_overflow */
00165         coff_i860_reloc,       /* special_function */
00166         "dir32",               /* name */
00167         TRUE,                 /* partial_inplace */
00168         0xffffffff,            /* src_mask */
00169         0xffffffff,            /* dst_mask */
00170         TRUE),                /* pcrel_offset */
00171   /* {7}, */
00172   HOWTO (R_IMAGEBASE,            /* type */
00173         0,                    /* rightshift */
00174         2,                    /* size (0 = byte, 1 = short, 2 = long) */
00175         32,                   /* bitsize */
00176         FALSE,                       /* pc_relative */
00177         0,                    /* bitpos */
00178         complain_overflow_bitfield, /* complain_on_overflow */
00179         coff_i860_reloc,       /* special_function */
00180         "rva32",                /* name */
00181         TRUE,                 /* partial_inplace */
00182         0xffffffff,            /* src_mask */
00183         0xffffffff,            /* dst_mask */
00184         FALSE),                /* pcrel_offset */
00185   EMPTY_HOWTO (010),
00186   EMPTY_HOWTO (011),
00187   EMPTY_HOWTO (012),
00188   EMPTY_HOWTO (013),
00189   EMPTY_HOWTO (014),
00190   EMPTY_HOWTO (015),
00191   EMPTY_HOWTO (016),
00192   HOWTO (R_RELBYTE,         /* type */
00193         0,                  /* rightshift */
00194         0,                  /* size (0 = byte, 1 = short, 2 = long) */
00195         8,                  /* bitsize */
00196         FALSE,                     /* pc_relative */
00197         0,                  /* bitpos */
00198         complain_overflow_bitfield, /* complain_on_overflow */
00199         coff_i860_reloc,    /* special_function */
00200         "8",                /* name */
00201         TRUE,               /* partial_inplace */
00202         0x000000ff,         /* src_mask */
00203         0x000000ff,         /* dst_mask */
00204         PCRELOFFSET),              /* pcrel_offset */
00205   HOWTO (R_RELWORD,         /* type */
00206         0,                  /* rightshift */
00207         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00208         16,                 /* bitsize */
00209         FALSE,                     /* pc_relative */
00210         0,                  /* bitpos */
00211         complain_overflow_bitfield, /* complain_on_overflow */
00212         coff_i860_reloc,    /* special_function */
00213         "16",               /* name */
00214         TRUE,               /* partial_inplace */
00215         0x0000ffff,         /* src_mask */
00216         0x0000ffff,         /* dst_mask */
00217         PCRELOFFSET),              /* pcrel_offset */
00218   HOWTO (R_RELLONG,         /* type */
00219         0,                  /* rightshift */
00220         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00221         32,                 /* bitsize */
00222         FALSE,                     /* pc_relative */
00223         0,                  /* bitpos */
00224         complain_overflow_bitfield, /* complain_on_overflow */
00225         coff_i860_reloc,    /* special_function */
00226         "32",               /* name */
00227         TRUE,               /* partial_inplace */
00228         0xffffffff,         /* src_mask */
00229         0xffffffff,         /* dst_mask */
00230         PCRELOFFSET),              /* pcrel_offset */
00231   HOWTO (R_PCRBYTE,         /* type */
00232         0,                  /* rightshift */
00233         0,                  /* size (0 = byte, 1 = short, 2 = long) */
00234         8,                  /* bitsize */
00235         TRUE,               /* pc_relative */
00236         0,                  /* bitpos */
00237         complain_overflow_signed, /* complain_on_overflow */
00238         coff_i860_reloc,    /* special_function */
00239         "DISP8",            /* name */
00240         TRUE,               /* partial_inplace */
00241         0x000000ff,         /* src_mask */
00242         0x000000ff,         /* dst_mask */
00243         PCRELOFFSET),              /* pcrel_offset */
00244   HOWTO (R_PCRWORD,         /* type */
00245         0,                  /* rightshift */
00246         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00247         16,                 /* bitsize */
00248         TRUE,               /* pc_relative */
00249         0,                  /* bitpos */
00250         complain_overflow_signed, /* complain_on_overflow */
00251         coff_i860_reloc,    /* special_function */
00252         "DISP16",           /* name */
00253         TRUE,               /* partial_inplace */
00254         0x0000ffff,         /* src_mask */
00255         0x0000ffff,         /* dst_mask */
00256         PCRELOFFSET),              /* pcrel_offset */
00257   HOWTO (R_PCRLONG,         /* type */
00258         0,                  /* rightshift */
00259         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00260         32,                 /* bitsize */
00261         TRUE,               /* pc_relative */
00262         0,                  /* bitpos */
00263         complain_overflow_signed, /* complain_on_overflow */
00264         coff_i860_reloc,    /* special_function */
00265         "DISP32",           /* name */
00266         TRUE,               /* partial_inplace */
00267         0xffffffff,         /* src_mask */
00268         0xffffffff,         /* dst_mask */
00269         PCRELOFFSET),              /* pcrel_offset */
00270   EMPTY_HOWTO (0x15),
00271   EMPTY_HOWTO (0x16),
00272   EMPTY_HOWTO (0x17),
00273   EMPTY_HOWTO (0x18),
00274   EMPTY_HOWTO (0x19),
00275   EMPTY_HOWTO (0x1a),
00276   EMPTY_HOWTO (0x1b),
00277   HOWTO (COFF860_R_PAIR,    /* type */
00278         0,                  /* rightshift */
00279         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00280         16,                 /* bitsize */
00281         FALSE,                     /* pc_relative */
00282         0,                  /* bitpos */
00283         complain_overflow_dont, /* complain_on_overflow */
00284         coff_i860_reloc_nyi,       /* special_function */
00285         "PAIR",             /* name */
00286         FALSE,                     /* partial_inplace */
00287         0xffff,             /* src_mask */
00288         0xffff,             /* dst_mask */
00289         FALSE),              /* pcrel_offset */
00290   EMPTY_HOWTO (0x1d),
00291   HOWTO (COFF860_R_HIGH,    /* type */
00292         16,                 /* rightshift */
00293         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00294         16,                 /* bitsize */
00295         FALSE,                     /* pc_relative */
00296         0,                  /* bitpos */
00297         complain_overflow_dont, /* complain_on_overflow */
00298         coff_i860_reloc,    /* special_function */
00299         "HIGH",             /* name */
00300         FALSE,                     /* partial_inplace */
00301         0xffff,             /* src_mask */
00302         0xffff,             /* dst_mask */
00303         FALSE),              /* pcrel_offset */
00304   HOWTO (COFF860_R_LOW0,        /* type */
00305         0,                  /* rightshift */
00306         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00307         16,                 /* bitsize */
00308         FALSE,                     /* pc_relative */
00309         0,                  /* bitpos */
00310         complain_overflow_dont, /* complain_on_overflow */
00311         coff_i860_reloc,    /* special_function */
00312         "LOW0",             /* name */
00313         FALSE,                     /* partial_inplace */
00314         0xffff,             /* src_mask */
00315         0xffff,             /* dst_mask */
00316         FALSE),              /* pcrel_offset */
00317   HOWTO (COFF860_R_LOW1,        /* type */
00318         0,                  /* rightshift */
00319         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00320         16,                 /* bitsize */
00321         FALSE,                     /* pc_relative */
00322         0,                  /* bitpos */
00323         complain_overflow_dont, /* complain_on_overflow */
00324         coff_i860_reloc,    /* special_function */
00325         "LOW1",             /* name */
00326         FALSE,                     /* partial_inplace */
00327         0xfffe,             /* src_mask */
00328         0xfffe,             /* dst_mask */
00329         FALSE),              /* pcrel_offset */
00330   HOWTO (COFF860_R_LOW2,        /* type */
00331         0,                  /* rightshift */
00332         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00333         16,                 /* bitsize */
00334         FALSE,                     /* pc_relative */
00335         0,                  /* bitpos */
00336         complain_overflow_dont, /* complain_on_overflow */
00337         coff_i860_reloc,    /* special_function */
00338         "LOW2",             /* name */
00339         FALSE,                     /* partial_inplace */
00340         0xfffc,             /* src_mask */
00341         0xfffc,             /* dst_mask */
00342         FALSE),              /* pcrel_offset */
00343   HOWTO (COFF860_R_LOW3,        /* type */
00344         0,                  /* rightshift */
00345         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00346         16,                 /* bitsize */
00347         FALSE,                     /* pc_relative */
00348         0,                  /* bitpos */
00349         complain_overflow_dont, /* complain_on_overflow */
00350         coff_i860_reloc,    /* special_function */
00351         "LOW3",             /* name */
00352         FALSE,                     /* partial_inplace */
00353         0xfff8,             /* src_mask */
00354         0xfff8,             /* dst_mask */
00355         FALSE),              /* pcrel_offset */
00356   HOWTO (COFF860_R_LOW4,        /* type */
00357         0,                  /* rightshift */
00358         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00359         16,                 /* bitsize */
00360         FALSE,                     /* pc_relative */
00361         0,                  /* bitpos */
00362         complain_overflow_dont, /* complain_on_overflow */
00363         coff_i860_reloc,    /* special_function */
00364         "LOW4",             /* name */
00365         FALSE,                     /* partial_inplace */
00366         0xfff0,             /* src_mask */
00367         0xfff0,             /* dst_mask */
00368         FALSE),              /* pcrel_offset */
00369   HOWTO (COFF860_R_SPLIT0,      /* type */
00370         0,                  /* rightshift */
00371         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00372         16,                 /* bitsize */
00373         FALSE,                     /* pc_relative */
00374         0,                  /* bitpos */
00375         complain_overflow_dont, /* complain_on_overflow */
00376         coff_i860_reloc_nyi,       /* special_function */
00377         "SPLIT0",           /* name */
00378         FALSE,                     /* partial_inplace */
00379         0x1f07ff,           /* src_mask */
00380         0x1f07ff,           /* dst_mask */
00381         FALSE),              /* pcrel_offset */
00382   HOWTO (COFF860_R_SPLIT1,      /* type */
00383         0,                  /* rightshift */
00384         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00385         16,                 /* bitsize */
00386         FALSE,                     /* pc_relative */
00387         0,                  /* bitpos */
00388         complain_overflow_dont, /* complain_on_overflow */
00389         coff_i860_reloc_nyi,       /* special_function */
00390         "SPLIT1",           /* name */
00391         FALSE,                     /* partial_inplace */
00392         0x1f07fe,           /* src_mask */
00393         0x1f07fe,           /* dst_mask */
00394         FALSE),              /* pcrel_offset */
00395   HOWTO (COFF860_R_SPLIT2,      /* type */
00396         0,                  /* rightshift */
00397         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00398         16,                 /* bitsize */
00399         FALSE,                     /* pc_relative */
00400         0,                  /* bitpos */
00401         complain_overflow_dont, /* complain_on_overflow */
00402         coff_i860_reloc_nyi,       /* special_function */
00403         "SPLIT2",           /* name */
00404         FALSE,                     /* partial_inplace */
00405         0x1f07fc,           /* src_mask */
00406         0x1f07fc,           /* dst_mask */
00407         FALSE),              /* pcrel_offset */
00408   HOWTO (COFF860_R_HIGHADJ,     /* type */
00409         0,                  /* rightshift */
00410         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00411         16,                 /* bitsize */
00412         FALSE,                     /* pc_relative */
00413         0,                  /* bitpos */
00414         complain_overflow_dont, /* complain_on_overflow */
00415         coff_i860_reloc_nyi,       /* special_function */
00416         "HIGHADJ",          /* name */
00417         FALSE,                     /* partial_inplace */
00418         0xffff,             /* src_mask */
00419         0xffff,             /* dst_mask */
00420         FALSE),              /* pcrel_offset */
00421   HOWTO (COFF860_R_BRADDR,      /* type */
00422         2,                  /* rightshift */
00423         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00424         26,                 /* bitsize */
00425         TRUE,               /* pc_relative */
00426         0,                  /* bitpos */
00427         complain_overflow_bitfield, /* complain_on_overflow */
00428         coff_i860_reloc_nyi,       /* special_function */
00429         "BRADDR",           /* name */
00430         FALSE,                     /* partial_inplace */
00431         0x3ffffff,          /* src_mask */
00432         0x3ffffff,          /* dst_mask */
00433         TRUE)                /* pcrel_offset */
00434 };
00435 
00436 /* Turn a howto into a reloc number.  */
00437 
00438 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
00439 #define BADMAG(x) I860BADMAG(x)
00440 #define I860 1                     /* Customize coffcode.h */
00441 
00442 #define RTYPE2HOWTO(cache_ptr, dst)                                   \
00443   ((cache_ptr)->howto =                                               \
00444    ((dst)->r_type < sizeof (howto_table) / sizeof (howto_table[0])    \
00445     ? howto_table + (dst)->r_type                              \
00446     : NULL))
00447 
00448 /* For 860 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
00449    library.  On some other COFF targets STYP_BSS is normally
00450    STYP_NOLOAD.  */
00451 #define BSS_NOLOAD_IS_SHARED_LIBRARY
00452 
00453 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
00454    the object file contains the value of the common symbol.  By the
00455    time this is called, the linker may be using a different symbol
00456    from a different object file with a different value.  Therefore, we
00457    hack wildly to locate the original symbol from this file so that we
00458    can make the correct adjustment.  This macro sets coffsym to the
00459    symbol from the original file, and uses it to set the addend value
00460    correctly.  If this is not a common symbol, the usual addend
00461    calculation is done, except that an additional tweak is needed for
00462    PC relative relocs.
00463    FIXME: This macro refers to symbols and asect; these are from the
00464    calling function, not the macro arguments.  */
00465 
00466 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)
00467 
00468 /* We use the special COFF backend linker.  */
00469 #define coff_relocate_section _bfd_coff_generic_relocate_section
00470 
00471 static reloc_howto_type *
00472 coff_i860_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
00473                        asection *sec,
00474                        struct internal_reloc *rel,
00475                        struct coff_link_hash_entry *h,
00476                        struct internal_syment *sym,
00477                        bfd_vma *addendp)
00478 {
00479 
00480   reloc_howto_type *howto;
00481 
00482   if (rel->r_type > sizeof (howto_table) / sizeof (howto_table[0]))
00483     {
00484       bfd_set_error (bfd_error_bad_value);
00485       return NULL;
00486     }
00487 
00488   howto = howto_table + rel->r_type;
00489 
00490   if (howto->pc_relative)
00491     *addendp += sec->vma;
00492 
00493   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
00494     {
00495       /* This is a common symbol.  The section contents include the
00496         size (sym->n_value) as an addend.  The relocate_section
00497         function will be adding in the final value of the symbol.  We
00498         need to subtract out the current size in order to get the
00499         correct result.  */
00500 
00501       BFD_ASSERT (h != NULL);
00502 
00503       /* I think we *do* want to bypass this.  If we don't, I have seen some data
00504         parameters get the wrong relocation address.  If I link two versions
00505         with and without this section bypassed and then do a binary comparison,
00506         the addresses which are different can be looked up in the map.  The
00507         case in which this section has been bypassed has addresses which correspond
00508         to values I can find in the map.  */
00509       *addendp -= sym->n_value;
00510     }
00511 
00512   /* If the output symbol is common (in which case this must be a
00513      relocatable link), we need to add in the final size of the
00514      common symbol.  */
00515   if (h != NULL && h->root.type == bfd_link_hash_common)
00516     *addendp += h->root.u.c.size;
00517 
00518   return howto;
00519 }
00520 
00521 static reloc_howto_type *
00522 coff_i860_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00523                           bfd_reloc_code_real_type code)
00524 {
00525   switch (code)
00526     {
00527     case BFD_RELOC_32:
00528       return howto_table + R_DIR32;
00529     case BFD_RELOC_860_PC26:
00530       return howto_table + COFF860_R_BRADDR;
00531     case BFD_RELOC_860_PC16:
00532       /* ??? How to handle PC16 for COFF?  SPLIT0 is close for now.  */
00533       return howto_table + COFF860_R_SPLIT0;
00534     case BFD_RELOC_860_LOW0:
00535       return howto_table + COFF860_R_LOW0;
00536     case BFD_RELOC_860_SPLIT0:
00537       return howto_table + COFF860_R_SPLIT0;
00538     case BFD_RELOC_860_LOW1:
00539       return howto_table + COFF860_R_LOW1;
00540     case BFD_RELOC_860_SPLIT1:
00541       return howto_table + COFF860_R_SPLIT1;
00542     case BFD_RELOC_860_LOW2:
00543       return howto_table + COFF860_R_LOW2;
00544     case BFD_RELOC_860_SPLIT2:
00545       return howto_table + COFF860_R_SPLIT2;
00546     case BFD_RELOC_860_LOW3:
00547       return howto_table + COFF860_R_LOW3;
00548     case BFD_RELOC_860_HIGHADJ:
00549       return howto_table + COFF860_R_HIGHADJ;
00550     case BFD_RELOC_860_HIGH:
00551       return howto_table + COFF860_R_HIGH;
00552     default:
00553       BFD_FAIL ();
00554       return 0;
00555     }
00556 }
00557 
00558 static reloc_howto_type *
00559 coff_i860_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00560                           const char *r_name)
00561 {
00562   unsigned int i;
00563 
00564   for (i = 0; i < sizeof (howto_table) / sizeof (howto_table[0]); i++)
00565     if (howto_table[i].name != NULL
00566        && strcasecmp (howto_table[i].name, r_name) == 0)
00567       return &howto_table[i];
00568 
00569   return NULL;
00570 }
00571 
00572 /* This is called from coff_slurp_reloc_table for each relocation
00573    entry.  This special handling is due to the `PAIR' relocation
00574    which has a different meaning for the `r_symndx' field.  */
00575 
00576 static void
00577 i860_reloc_processing (arelent *cache_ptr, struct internal_reloc *dst,
00578                      asymbol **symbols, bfd *abfd, asection *asect)
00579 {
00580   if (dst->r_type == COFF860_R_PAIR)
00581     {
00582       /* Handle the PAIR relocation specially.  */
00583       cache_ptr->howto = howto_table + dst->r_type;
00584       cache_ptr->address = dst->r_vaddr;
00585       cache_ptr->addend = dst->r_symndx;
00586       cache_ptr->sym_ptr_ptr= bfd_abs_section_ptr->symbol_ptr_ptr;
00587     }
00588   else
00589     {
00590       /* For every other relocation, do exactly what coff_slurp_reloc_table
00591          would do (which this code is taken directly from).  */
00592       asymbol *ptr = NULL;
00593       cache_ptr->address = dst->r_vaddr;
00594 
00595       if (dst->r_symndx != -1)
00596        {
00597          if (dst->r_symndx < 0 || dst->r_symndx >= obj_conv_table_size (abfd))
00598            {
00599              (*_bfd_error_handler)
00600               (_("%B: warning: illegal symbol index %ld in relocs"),
00601                abfd, dst->r_symndx);
00602              cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
00603              ptr = NULL;
00604            }
00605          else
00606            {
00607              cache_ptr->sym_ptr_ptr = (symbols
00608                                    + obj_convert (abfd)[dst->r_symndx]);
00609              ptr = *(cache_ptr->sym_ptr_ptr);
00610            }
00611        }
00612       else
00613        {
00614          cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
00615          ptr = NULL;
00616        }
00617 
00618       /* The symbols definitions that we have read in have been
00619         relocated as if their sections started at 0. But the offsets
00620         refering to the symbols in the raw data have not been
00621         modified, so we have to have a negative addend to compensate.
00622 
00623         Note that symbols which used to be common must be left alone.  */
00624 
00625       /* Calculate any reloc addend by looking at the symbol.  */
00626       CALC_ADDEND (abfd, ptr, (*dst), cache_ptr);
00627 
00628       cache_ptr->address -= asect->vma;
00629 
00630       /* Fill in the cache_ptr->howto field from dst->r_type.  */
00631       RTYPE2HOWTO (cache_ptr, dst);
00632     }
00633 }
00634 
00635 #define coff_rtype_to_howto        coff_i860_rtype_to_howto
00636 #define coff_bfd_reloc_type_lookup coff_i860_reloc_type_lookup
00637 #define coff_bfd_reloc_name_lookup coff_i860_reloc_name_lookup
00638 
00639 #define RELOC_PROCESSING(relent, reloc, symbols, abfd, section) \
00640   i860_reloc_processing (relent, reloc, symbols, abfd, section)
00641 
00642 #include "coffcode.h"
00643 
00644 static const bfd_target *
00645 i3coff_object_p(bfd *a)
00646 {
00647   return coff_object_p (a);
00648 }
00649 
00650 const bfd_target
00651 #ifdef TARGET_SYM
00652   TARGET_SYM =
00653 #else
00654   i860coff_vec =
00655 #endif
00656 {
00657 #ifdef TARGET_NAME
00658   TARGET_NAME,
00659 #else
00660   "coff-i860",                     /* name */
00661 #endif
00662   bfd_target_coff_flavour,
00663   BFD_ENDIAN_LITTLE,        /* data byte order is little */
00664   BFD_ENDIAN_LITTLE,        /* header byte order is little */
00665 
00666   (HAS_RELOC | EXEC_P |            /* object flags */
00667    HAS_LINENO | HAS_DEBUG |
00668    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
00669 
00670   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
00671   '_',                      /* leading underscore */
00672   '/',                      /* ar_pad_char */
00673   15,                       /* ar_max_namelen */
00674 
00675   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00676      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00677      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
00678   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00679      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00680      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
00681 
00682 /* Note that we allow an object file to be treated as a core file as well.  */
00683     {_bfd_dummy_target, i3coff_object_p, /* bfd_check_format */
00684        bfd_generic_archive_p, i3coff_object_p},
00685     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
00686        bfd_false},
00687     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
00688        _bfd_write_archive_contents, bfd_false},
00689 
00690      BFD_JUMP_TABLE_GENERIC (coff),
00691      BFD_JUMP_TABLE_COPY (coff),
00692      BFD_JUMP_TABLE_CORE (_bfd_nocore),
00693      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
00694      BFD_JUMP_TABLE_SYMBOLS (coff),
00695      BFD_JUMP_TABLE_RELOCS (coff),
00696      BFD_JUMP_TABLE_WRITE (coff),
00697      BFD_JUMP_TABLE_LINK (coff),
00698      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
00699 
00700   NULL,
00701 
00702   COFF_SWAP_TABLE
00703 };