Back to index

cell-binutils  2.17cvs20070401
elf32-iq2000.c
Go to the documentation of this file.
00001 /* IQ2000-specific support for 32-bit ELF.
00002    Copyright (C) 2003, 2004, 2005, 2006, 2007
00003    Free Software Foundation, Inc.
00004 
00005    This file is part of BFD, the Binary File Descriptor library.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00020 
00021 #include "bfd.h"
00022 #include "sysdep.h"
00023 #include "libbfd.h"
00024 #include "elf-bfd.h"
00025 #include "elf/iq2000.h"
00026 
00027 /* Forward declarations.  */
00028 
00029 static bfd_reloc_status_type iq2000_elf_howto_hi16_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
00030 
00031 
00032 static reloc_howto_type iq2000_elf_howto_table [] =
00033 {
00034   /* This reloc does nothing.  */
00035 
00036   HOWTO (R_IQ2000_NONE,                 /* type */
00037         0,                       /* rightshift */
00038         2,                       /* size (0 = byte, 1 = short, 2 = long) */
00039         32,                      /* bitsize */
00040         FALSE,                          /* pc_relative */
00041         0,                       /* bitpos */
00042         complain_overflow_bitfield, /* complain_on_overflow */
00043         bfd_elf_generic_reloc,          /* special_function */
00044         "R_IQ2000_NONE",         /* name */
00045         FALSE,                          /* partial_inplace */
00046         0,                       /* src_mask */
00047         0,                       /* dst_mask */
00048         FALSE),                  /* pcrel_offset */
00049 
00050   /* A 16 bit absolute relocation.  */
00051   HOWTO (R_IQ2000_16,                   /* type */
00052         0,                       /* rightshift */
00053         1,                       /* size (0 = byte, 1 = short, 2 = long) */
00054         16,                      /* bitsize */
00055         FALSE,                          /* pc_relative */
00056         0,                       /* bitpos */
00057         complain_overflow_bitfield, /* complain_on_overflow */
00058         bfd_elf_generic_reloc,          /* special_function */
00059         "R_IQ2000_16",                  /* name */
00060         FALSE,                          /* partial_inplace */
00061         0x0000,                  /* src_mask */
00062         0xffff,                  /* dst_mask */
00063         FALSE),                  /* pcrel_offset */
00064 
00065   /* A 32 bit absolute relocation.  */
00066   HOWTO (R_IQ2000_32,                   /* type */
00067         0,                       /* rightshift */
00068         2,                       /* size (0 = byte, 1 = short, 2 = long) */
00069         31,                      /* bitsize */
00070         FALSE,                          /* pc_relative */
00071         0,                       /* bitpos */
00072         complain_overflow_bitfield, /* complain_on_overflow */
00073         bfd_elf_generic_reloc,          /* special_function */
00074         "R_IQ2000_32",                  /* name */
00075         FALSE,                          /* partial_inplace */
00076         0x00000000,              /* src_mask */
00077         0x7fffffff,              /* dst_mask */
00078         FALSE),                  /* pcrel_offset */
00079 
00080   /* 26 bit branch address.  */
00081   HOWTO (R_IQ2000_26,              /* type */
00082         2,                  /* rightshift */
00083         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00084         26,                 /* bitsize */
00085         FALSE,                     /* pc_relative */
00086         0,                  /* bitpos */
00087         complain_overflow_dont, /* complain_on_overflow */
00088                             /* This needs complex overflow
00089                                detection, because the upper four
00090                                bits must match the PC.  */
00091         bfd_elf_generic_reloc,     /* special_function */
00092         "R_IQ2000_26",             /* name */
00093         FALSE,                     /* partial_inplace */
00094         0x00000000,         /* src_mask */
00095         0x03ffffff,         /* dst_mask */
00096         FALSE),             /* pcrel_offset */
00097 
00098   /* 16 bit PC relative reference.  */
00099   HOWTO (R_IQ2000_PC16,            /* type */
00100         2,                  /* rightshift */
00101         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00102         16,                 /* bitsize */
00103         TRUE,               /* pc_relative */
00104         0,                  /* bitpos */
00105         complain_overflow_signed, /* complain_on_overflow */
00106         bfd_elf_generic_reloc,     /* special_function */
00107         "R_IQ2000_PC16",    /* name */
00108         FALSE,                     /* partial_inplace */
00109         0x0000,             /* src_mask */
00110         0xffff,             /* dst_mask */
00111         TRUE),                     /* pcrel_offset */
00112 
00113   /* high 16 bits of symbol value.  */
00114   HOWTO (R_IQ2000_HI16,            /* type */
00115         16,                 /* rightshift */
00116         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00117         15,                 /* bitsize */
00118         FALSE,                     /* pc_relative */
00119         0,                  /* bitpos */
00120         complain_overflow_dont, /* complain_on_overflow */
00121         iq2000_elf_howto_hi16_reloc,      /* special_function */
00122         "R_IQ2000_HI16",    /* name */
00123         FALSE,                     /* partial_inplace */
00124         0x0000,             /* src_mask */
00125         0x7fff,             /* dst_mask */
00126         FALSE),             /* pcrel_offset */
00127 
00128   /* Low 16 bits of symbol value.  */
00129   HOWTO (R_IQ2000_LO16,            /* type */
00130         0,                  /* rightshift */
00131         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00132         16,                 /* bitsize */
00133         FALSE,                     /* pc_relative */
00134         0,                  /* bitpos */
00135         complain_overflow_dont, /* complain_on_overflow */
00136         bfd_elf_generic_reloc,     /* special_function */
00137         "R_IQ2000_LO16",    /* name */
00138         FALSE,                     /* partial_inplace */
00139         0x0000,             /* src_mask */
00140         0xffff,             /* dst_mask */
00141         FALSE),             /* pcrel_offset */
00142 
00143   /* 16-bit jump offset.  */
00144   HOWTO (R_IQ2000_OFFSET_16,       /* type */
00145         2,                  /* rightshift */
00146         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00147         16,                 /* bitsize */
00148         FALSE,                     /* pc_relative */
00149         0,                  /* bitpos */
00150         complain_overflow_dont, /* complain_on_overflow */
00151         bfd_elf_generic_reloc,     /* special_function */
00152         "R_IQ2000_OFFSET_16",      /* name */
00153         FALSE,                     /* partial_inplace */
00154         0x0000,             /* src_mask */
00155         0xffff,             /* dst_mask */
00156         FALSE),             /* pcrel_offset */
00157 
00158   /* 21-bit jump offset.  */
00159   HOWTO (R_IQ2000_OFFSET_21,       /* type */
00160         2,                  /* rightshift */
00161         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00162         21,                 /* bitsize */
00163         FALSE,                     /* pc_relative */
00164         0,                  /* bitpos */
00165         complain_overflow_dont, /* complain_on_overflow */
00166         bfd_elf_generic_reloc,     /* special_function */
00167         "R_IQ2000_OFFSET_21",      /* name */
00168         FALSE,                     /* partial_inplace */
00169         0x000000,           /* src_mask */
00170         0x1fffff,           /* dst_mask */
00171         FALSE),             /* pcrel_offset */
00172 
00173   /* unsigned high 16 bits of value.  */
00174   HOWTO (R_IQ2000_OFFSET_21,       /* type */
00175         16,                 /* rightshift */
00176         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00177         16,                 /* bitsize */
00178         FALSE,                     /* pc_relative */
00179         0,                  /* bitpos */
00180         complain_overflow_dont, /* complain_on_overflow */
00181         bfd_elf_generic_reloc,     /* special_function */
00182         "R_IQ2000_UHI16",   /* name */
00183         FALSE,                     /* partial_inplace */
00184         0x0000,             /* src_mask */
00185         0x7fff,             /* dst_mask */
00186         FALSE),             /* pcrel_offset */
00187 
00188   /* A 32 bit absolute debug relocation.  */
00189   HOWTO (R_IQ2000_32_DEBUG,      /* type */
00190         0,                       /* rightshift */
00191         2,                       /* size (0 = byte, 1 = short, 2 = long) */
00192         32,                      /* bitsize */
00193         FALSE,                          /* pc_relative */
00194         0,                       /* bitpos */
00195         complain_overflow_bitfield, /* complain_on_overflow */
00196         bfd_elf_generic_reloc,          /* special_function */
00197         "R_IQ2000_32",                  /* name */
00198         FALSE,                          /* partial_inplace */
00199         0x00000000,              /* src_mask */
00200         0xffffffff,              /* dst_mask */
00201         FALSE),                  /* pcrel_offset */
00202 
00203 };
00204 
00205 /* GNU extension to record C++ vtable hierarchy.  */
00206 static reloc_howto_type iq2000_elf_vtinherit_howto =
00207   HOWTO (R_IQ2000_GNU_VTINHERIT,    /* type */
00208         0,                     /* rightshift */
00209         2,                     /* size (0 = byte, 1 = short, 2 = long) */
00210         0,                     /* bitsize */
00211         FALSE,                        /* pc_relative */
00212         0,                     /* bitpos */
00213         complain_overflow_dont,   /* complain_on_overflow */
00214         NULL,                  /* special_function */
00215         "R_IQ2000_GNU_VTINHERIT",  /* name */
00216         FALSE,                        /* partial_inplace */
00217         0,                     /* src_mask */
00218         0,                     /* dst_mask */
00219         FALSE);                /* pcrel_offset */
00220 
00221 /* GNU extension to record C++ vtable member usage.  */
00222 static reloc_howto_type iq2000_elf_vtentry_howto =
00223   HOWTO (R_IQ2000_GNU_VTENTRY,        /* type */
00224         0,                     /* rightshift */
00225         2,                     /* size (0 = byte, 1 = short, 2 = long) */
00226         0,                     /* bitsize */
00227         FALSE,                        /* pc_relative */
00228         0,                     /* bitpos */
00229         complain_overflow_dont,   /* complain_on_overflow */
00230         NULL,                  /* special_function */
00231         "R_IQ2000_GNU_VTENTRY",    /* name */
00232         FALSE,                        /* partial_inplace */
00233         0,                     /* src_mask */
00234         0,                     /* dst_mask */
00235         FALSE);                /* pcrel_offset */
00236 
00237 
00238 static bfd_reloc_status_type
00239 iq2000_elf_howto_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED,
00240                           arelent *reloc_entry,
00241                           asymbol *symbol,
00242                           void * data,
00243                           asection *input_section,
00244                           bfd *output_bfd,
00245                           char **error_message ATTRIBUTE_UNUSED)
00246 {
00247   bfd_reloc_status_type ret;
00248   bfd_vma relocation;
00249 
00250   /* If we're relocating and this an external symbol,
00251      we don't want to change anything.  */
00252   if (output_bfd != (bfd *) NULL
00253       && (symbol->flags & BSF_SECTION_SYM) == 0
00254       && reloc_entry->addend == 0)
00255     {
00256       reloc_entry->address += input_section->output_offset;
00257       return bfd_reloc_ok;
00258     }
00259 
00260   if (bfd_is_com_section (symbol->section))
00261     relocation = 0;
00262   else
00263     relocation = symbol->value;
00264 
00265   relocation += symbol->section->output_section->vma;
00266   relocation += symbol->section->output_offset;
00267   relocation += reloc_entry->addend;
00268 
00269   /* If %lo will have sign-extension, compensate by add 0x10000 to hi portion.  */
00270   if (relocation & 0x8000)
00271     reloc_entry->addend += 0x10000;
00272 
00273   /* Now do the reloc in the usual way.    */
00274   ret = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
00275                             input_section, output_bfd, error_message);
00276 
00277   /* Put it back the way it was.  */
00278   if (relocation & 0x8000)
00279     reloc_entry->addend -= 0x10000;
00280 
00281   return ret;
00282 }
00283 
00284 static bfd_reloc_status_type
00285 iq2000_elf_relocate_hi16 (bfd *input_bfd,
00286                        Elf_Internal_Rela *relhi,
00287                        bfd_byte *contents,
00288                        bfd_vma value)
00289 {
00290   bfd_vma insn;
00291 
00292   insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
00293   
00294   value += relhi->r_addend;
00295   value &= 0x7fffffff; /* Mask off top-bit which is Harvard mask bit.  */
00296 
00297   /* If top-bit of %lo value is on, this means that %lo will
00298      sign-propagate and so we compensate by adding 1 to %hi value.  */
00299   if (value & 0x8000)
00300     value += 0x10000;
00301 
00302   value >>= 16; 
00303   insn = ((insn & ~0xFFFF) | value);
00304 
00305   bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
00306   return bfd_reloc_ok;
00307 }
00308 
00309 /* Map BFD reloc types to IQ2000 ELF reloc types.  */
00310 
00311 static reloc_howto_type *
00312 iq2000_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00313                        bfd_reloc_code_real_type code)
00314 {
00315   /* Note that the iq2000_elf_howto_table is indxed by the R_
00316      constants.       Thus, the order that the howto records appear in the
00317      table *must* match the order of the relocation types defined in
00318      include/elf/iq2000.h.  */
00319 
00320   switch (code)
00321     {
00322     case BFD_RELOC_NONE:
00323       return &iq2000_elf_howto_table[ (int) R_IQ2000_NONE];
00324     case BFD_RELOC_16:
00325       return &iq2000_elf_howto_table[ (int) R_IQ2000_16];
00326     case BFD_RELOC_32:
00327       return &iq2000_elf_howto_table[ (int) R_IQ2000_32];
00328     case BFD_RELOC_MIPS_JMP:
00329       return &iq2000_elf_howto_table[ (int) R_IQ2000_26];
00330     case BFD_RELOC_IQ2000_OFFSET_16:
00331       return &iq2000_elf_howto_table[ (int) R_IQ2000_OFFSET_16];
00332     case BFD_RELOC_IQ2000_OFFSET_21:
00333       return &iq2000_elf_howto_table[ (int) R_IQ2000_OFFSET_21];
00334     case BFD_RELOC_16_PCREL_S2:
00335       return &iq2000_elf_howto_table[ (int) R_IQ2000_PC16];
00336     case BFD_RELOC_HI16:
00337       return &iq2000_elf_howto_table[ (int) R_IQ2000_HI16];
00338     case BFD_RELOC_IQ2000_UHI16:
00339       return &iq2000_elf_howto_table[ (int) R_IQ2000_UHI16];
00340     case BFD_RELOC_LO16:
00341       return &iq2000_elf_howto_table[ (int) R_IQ2000_LO16];
00342     case BFD_RELOC_VTABLE_INHERIT:
00343       return &iq2000_elf_vtinherit_howto;
00344     case BFD_RELOC_VTABLE_ENTRY:
00345       return &iq2000_elf_vtentry_howto;
00346     default:
00347       /* Pacify gcc -Wall.  */
00348       return NULL;
00349     }
00350   return NULL;
00351 }
00352 
00353 static reloc_howto_type *
00354 iq2000_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
00355 {
00356   unsigned int i;
00357 
00358   for (i = 0;
00359        i < (sizeof (iq2000_elf_howto_table)
00360            / sizeof (iq2000_elf_howto_table[0]));
00361        i++)
00362     if (iq2000_elf_howto_table[i].name != NULL
00363        && strcasecmp (iq2000_elf_howto_table[i].name, r_name) == 0)
00364       return &iq2000_elf_howto_table[i];
00365 
00366   if (strcasecmp (iq2000_elf_vtinherit_howto.name, r_name) == 0)
00367     return &iq2000_elf_vtinherit_howto;
00368   if (strcasecmp (iq2000_elf_vtentry_howto.name, r_name) == 0)
00369     return &iq2000_elf_vtentry_howto;
00370 
00371   return NULL;
00372 }
00373 
00374 /* Perform a single relocation.     By default we use the standard BFD
00375    routines.  */
00376 
00377 static bfd_reloc_status_type
00378 iq2000_final_link_relocate (reloc_howto_type *   howto,
00379                          bfd *            input_bfd,
00380                          asection *              input_section,
00381                          bfd_byte *              contents,
00382                          Elf_Internal_Rela *     rel,
00383                          bfd_vma          relocation)
00384 {
00385   return _bfd_final_link_relocate (howto, input_bfd, input_section,
00386                                contents, rel->r_offset,
00387                                relocation, rel->r_addend);
00388 }
00389 
00390 /* Set the howto pointer for a IQ2000 ELF reloc.  */
00391 
00392 static void
00393 iq2000_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
00394                         arelent * cache_ptr,
00395                         Elf_Internal_Rela * dst)
00396 {
00397   unsigned int r_type;
00398 
00399   r_type = ELF32_R_TYPE (dst->r_info);
00400   switch (r_type)
00401     {
00402     case R_IQ2000_GNU_VTINHERIT:
00403       cache_ptr->howto = & iq2000_elf_vtinherit_howto;
00404       break;
00405 
00406     case R_IQ2000_GNU_VTENTRY:
00407       cache_ptr->howto = & iq2000_elf_vtentry_howto;
00408       break;
00409 
00410     default:
00411       cache_ptr->howto = & iq2000_elf_howto_table [r_type];
00412       break;
00413     }
00414 }
00415 
00416 /* Look through the relocs for a section during the first phase.
00417    Since we don't do .gots or .plts, we just need to consider the
00418    virtual table relocs for gc.     */
00419  
00420 static bfd_boolean
00421 iq2000_elf_check_relocs (bfd *abfd,
00422                       struct bfd_link_info *info,
00423                       asection *sec,
00424                       const Elf_Internal_Rela *relocs)
00425 {
00426   Elf_Internal_Shdr *symtab_hdr;
00427   struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
00428   const Elf_Internal_Rela *rel;
00429   const Elf_Internal_Rela *rel_end;
00430   bfd_boolean changed = FALSE;
00431   
00432   if (info->relocatable)
00433     return TRUE;
00434   
00435   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00436   sym_hashes = elf_sym_hashes (abfd);
00437   sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
00438   if (!elf_bad_symtab (abfd))
00439     sym_hashes_end -= symtab_hdr->sh_info;
00440   
00441   rel_end = relocs + sec->reloc_count;
00442   for (rel = relocs; rel < rel_end; rel++)
00443     {
00444       struct elf_link_hash_entry *h;
00445       unsigned long r_symndx;
00446       
00447       r_symndx = ELF32_R_SYM (rel->r_info);
00448       if (r_symndx < symtab_hdr->sh_info)
00449        h = NULL;
00450       else
00451        {
00452          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
00453          while (h->root.type == bfd_link_hash_indirect
00454                || h->root.type == bfd_link_hash_warning)
00455            h = (struct elf_link_hash_entry *) h->root.u.i.link;
00456        }
00457       
00458       switch (ELF32_R_TYPE (rel->r_info))
00459        {
00460          /* This relocation describes the C++ object vtable
00461             hierarchy.  Reconstruct it for later use during GC.  */
00462        case R_IQ2000_GNU_VTINHERIT:
00463          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
00464            return FALSE;
00465          break;
00466          
00467          /* This relocation describes which C++ vtable entries
00468             are actually used.  Record for later use during GC.  */
00469        case R_IQ2000_GNU_VTENTRY:
00470          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
00471            return FALSE;
00472          break;
00473 
00474        case R_IQ2000_32:
00475          /* For debug section, change to special harvard-aware relocations.  */
00476          if (CONST_STRNEQ (sec->name, ".debug")
00477              || CONST_STRNEQ (sec->name, ".stab")
00478              || CONST_STRNEQ (sec->name, ".eh_frame"))
00479            {
00480              ((Elf_Internal_Rela *) rel)->r_info
00481               = ELF32_R_INFO (ELF32_R_SYM (rel->r_info), R_IQ2000_32_DEBUG);
00482              changed = TRUE;
00483            }
00484          break;
00485        }
00486     }
00487 
00488   if (changed)
00489     /* Note that we've changed relocs, otherwise if !info->keep_memory
00490        we'll free the relocs and lose our changes.  */
00491     elf_section_data (sec)->relocs = (Elf_Internal_Rela *) relocs;
00492 
00493   return TRUE;
00494 }
00495 
00496 
00497 /* Relocate a IQ2000 ELF section.
00498    There is some attempt to make this function usable for many architectures,
00499    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
00500    if only to serve as a learning tool.
00501 
00502    The RELOCATE_SECTION function is called by the new ELF backend linker
00503    to handle the relocations for a section.
00504 
00505    The relocs are always passed as Rela structures; if the section
00506    actually uses Rel structures, the r_addend field will always be
00507    zero.
00508 
00509    This function is responsible for adjusting the section contents as
00510    necessary, and (if using Rela relocs and generating a relocatable
00511    output file) adjusting the reloc addend as necessary.
00512 
00513    This function does not have to worry about setting the reloc
00514    address or the reloc symbol index.
00515 
00516    LOCAL_SYMS is a pointer to the swapped in local symbols.
00517 
00518    LOCAL_SECTIONS is an array giving the section in the input file
00519    corresponding to the st_shndx field of each local symbol.
00520 
00521    The global hash table entry for the global symbols can be found
00522    via elf_sym_hashes (input_bfd).
00523 
00524    When generating relocatable output, this function must handle
00525    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
00526    going to be the section symbol corresponding to the output
00527    section, which means that the addend must be adjusted
00528    accordingly.       */
00529 
00530 static bfd_boolean
00531 iq2000_elf_relocate_section (bfd *             output_bfd ATTRIBUTE_UNUSED,
00532                           struct bfd_link_info *  info,
00533                           bfd *                input_bfd,
00534                           asection *                  input_section,
00535                           bfd_byte *                  contents,
00536                           Elf_Internal_Rela *     relocs,
00537                           Elf_Internal_Sym *          local_syms,
00538                           asection **          local_sections)
00539 {
00540   Elf_Internal_Shdr *              symtab_hdr;
00541   struct elf_link_hash_entry ** sym_hashes;
00542   Elf_Internal_Rela *              rel;
00543   Elf_Internal_Rela *              relend;
00544 
00545   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
00546   sym_hashes = elf_sym_hashes (input_bfd);
00547   relend     = relocs + input_section->reloc_count;
00548 
00549   for (rel = relocs; rel < relend; rel ++)
00550     {
00551       reloc_howto_type *       howto;
00552       unsigned long            r_symndx;
00553       Elf_Internal_Sym *       sym;
00554       asection *               sec;
00555       struct elf_link_hash_entry * h;
00556       bfd_vma                  relocation;
00557       bfd_reloc_status_type    r;
00558       const char *             name = NULL;
00559       int                      r_type;
00560       
00561       r_type = ELF32_R_TYPE (rel->r_info);
00562       
00563       if (   r_type == R_IQ2000_GNU_VTINHERIT
00564          || r_type == R_IQ2000_GNU_VTENTRY)
00565        continue;
00566       
00567       r_symndx = ELF32_R_SYM (rel->r_info);
00568 
00569       howto  = iq2000_elf_howto_table + ELF32_R_TYPE (rel->r_info);
00570       h            = NULL;
00571       sym    = NULL;
00572       sec    = NULL;
00573       
00574       if (r_symndx < symtab_hdr->sh_info)
00575        {
00576          sym = local_syms + r_symndx;
00577          sec = local_sections [r_symndx];
00578          relocation = (sec->output_section->vma
00579                      + sec->output_offset
00580                      + sym->st_value);
00581          
00582          name = bfd_elf_string_from_elf_section
00583            (input_bfd, symtab_hdr->sh_link, sym->st_name);
00584          name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
00585        }
00586       else
00587        {
00588          bfd_boolean unresolved_reloc;
00589          bfd_boolean warned;
00590 
00591          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
00592                                r_symndx, symtab_hdr, sym_hashes,
00593                                h, sec, relocation,
00594                                unresolved_reloc, warned);
00595 
00596          name = h->root.root.string;
00597        }
00598 
00599       if (sec != NULL && elf_discarded_section (sec))
00600        {
00601          /* For relocs against symbols from removed linkonce sections,
00602             or sections discarded by a linker script, we just want the
00603             section contents zeroed.  Avoid any special processing.  */
00604          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
00605          rel->r_info = 0;
00606          rel->r_addend = 0;
00607          continue;
00608        }
00609 
00610       if (info->relocatable)
00611        continue;
00612 
00613       switch (r_type)
00614        {
00615        case R_IQ2000_HI16:
00616          r = iq2000_elf_relocate_hi16 (input_bfd, rel, contents, relocation);
00617          break;
00618 
00619        case R_IQ2000_PC16:
00620          rel->r_addend -= 4;
00621          /* Fall through.  */
00622 
00623        default:
00624          r = iq2000_final_link_relocate (howto, input_bfd, input_section,
00625                                     contents, rel, relocation);
00626          break;
00627        }
00628 
00629       if (r != bfd_reloc_ok)
00630        {
00631          const char * msg = (const char *) NULL;
00632 
00633          switch (r)
00634            {
00635            case bfd_reloc_overflow:
00636              r = info->callbacks->reloc_overflow
00637               (info, (h ? &h->root : NULL), name, howto->name,
00638                (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
00639              break;
00640              
00641            case bfd_reloc_undefined:
00642              r = info->callbacks->undefined_symbol
00643               (info, name, input_bfd, input_section, rel->r_offset, TRUE);
00644              break;
00645              
00646            case bfd_reloc_outofrange:
00647              msg = _("internal error: out of range error");
00648              break;
00649 
00650            case bfd_reloc_notsupported:
00651              msg = _("internal error: unsupported relocation error");
00652              break;
00653 
00654            case bfd_reloc_dangerous:
00655              msg = _("internal error: dangerous relocation");
00656              break;
00657 
00658            default:
00659              msg = _("internal error: unknown error");
00660              break;
00661            }
00662 
00663          if (msg)
00664            r = info->callbacks->warning
00665              (info, msg, name, input_bfd, input_section, rel->r_offset);
00666 
00667          if (! r)
00668            return FALSE;
00669        }
00670     }
00671 
00672   return TRUE;
00673 }
00674 
00675 
00676 /* Return the section that should be marked against GC for a given
00677    relocation.       */
00678 
00679 static asection *
00680 iq2000_elf_gc_mark_hook (asection *sec,
00681                       struct bfd_link_info *info,
00682                       Elf_Internal_Rela *rel,
00683                       struct elf_link_hash_entry *h,
00684                       Elf_Internal_Sym *sym)
00685 {
00686   if (h != NULL)
00687     switch (ELF32_R_TYPE (rel->r_info))
00688       {
00689       case R_IQ2000_GNU_VTINHERIT:
00690       case R_IQ2000_GNU_VTENTRY:
00691        return NULL;
00692       }
00693 
00694   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
00695 }
00696 
00697 
00698 /* Return the MACH for an e_flags value.  */
00699 
00700 static int
00701 elf32_iq2000_machine (bfd *abfd)
00702 {
00703   switch (elf_elfheader (abfd)->e_flags & EF_IQ2000_CPU_MASK)
00704     {
00705     case EF_IQ2000_CPU_IQ10:
00706       return bfd_mach_iq10;
00707 
00708     case EF_IQ2000_CPU_IQ2000:
00709     default:
00710       return bfd_mach_iq2000;
00711     }
00712 }
00713 
00714 
00715 /* Function to set the ELF flag bits.  */
00716 
00717 static bfd_boolean
00718 iq2000_elf_set_private_flags (bfd *abfd, flagword flags)
00719 {
00720   elf_elfheader (abfd)->e_flags = flags;
00721   elf_flags_init (abfd) = TRUE;
00722   return TRUE;
00723 }
00724 
00725 /* Copy backend specific data from one object module to another.  */
00726 
00727 static bfd_boolean
00728 iq2000_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
00729 {
00730   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
00731       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
00732     return TRUE;
00733 
00734   BFD_ASSERT (!elf_flags_init (obfd)
00735              || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
00736 
00737   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
00738   elf_flags_init (obfd) = TRUE;
00739   return TRUE;
00740 }
00741 
00742 /* Merge backend specific data from an object
00743    file to the output object file when linking.  */
00744 
00745 static bfd_boolean
00746 iq2000_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
00747 {
00748   flagword old_flags, old_partial;
00749   flagword new_flags, new_partial;
00750   bfd_boolean error = FALSE;
00751   char new_opt[80];
00752   char old_opt[80];
00753 
00754   new_opt[0] = old_opt[0] = '\0';
00755   new_flags = elf_elfheader (ibfd)->e_flags;
00756   old_flags = elf_elfheader (obfd)->e_flags;
00757 
00758   if (!elf_flags_init (obfd))
00759     {
00760       /* First call, no flags set.  */
00761       elf_flags_init (obfd) = TRUE;
00762       elf_elfheader (obfd)->e_flags = new_flags;
00763     }
00764 
00765   else if (new_flags != old_flags)
00766     {
00767       /* Warn if different cpu is used, but allow a
00768         specific cpu to override the generic cpu.  */
00769       new_partial = (new_flags & EF_IQ2000_CPU_MASK);
00770       old_partial = (old_flags & EF_IQ2000_CPU_MASK);
00771 
00772       if (new_partial != old_partial)
00773        {
00774          switch (new_partial)
00775            {
00776            case EF_IQ2000_CPU_IQ10:
00777              strcat (new_opt, " -m10");
00778              break;
00779 
00780            default:
00781            case EF_IQ2000_CPU_IQ2000:
00782              strcat (new_opt, " -m2000");
00783              break;
00784            }
00785 
00786          switch (old_partial)
00787            {
00788            case EF_IQ2000_CPU_IQ10:
00789              strcat (old_opt, " -m10");
00790              break;
00791 
00792            default:
00793            case EF_IQ2000_CPU_IQ2000:
00794              strcat (old_opt, " -m2000");
00795              break;
00796            }
00797        }
00798       
00799       /* Print out any mismatches from above.  */
00800       if (new_opt[0])
00801        {
00802          error = TRUE;
00803          _bfd_error_handler
00804            (_("%s: compiled with %s and linked with modules compiled with %s"),
00805             bfd_get_filename (ibfd), new_opt, old_opt);
00806        }
00807 
00808       new_flags &= ~ EF_IQ2000_ALL_FLAGS;
00809       old_flags &= ~ EF_IQ2000_ALL_FLAGS;
00810 
00811       /* Warn about any other mismatches.  */
00812       if (new_flags != old_flags)
00813        {
00814          error = TRUE;
00815 
00816          _bfd_error_handler
00817            (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
00818             bfd_get_filename (ibfd), (long)new_flags, (long)old_flags);
00819        }
00820     }
00821 
00822   if (error)
00823     bfd_set_error (bfd_error_bad_value);
00824 
00825   return !error;
00826 }
00827 
00828 
00829 static bfd_boolean
00830 iq2000_elf_print_private_bfd_data (bfd *abfd, void * ptr)
00831 {
00832   FILE *file = (FILE *) ptr;
00833   flagword flags;
00834 
00835   BFD_ASSERT (abfd != NULL && ptr != NULL);
00836 
00837   /* Print normal ELF private data.  */
00838   _bfd_elf_print_private_bfd_data (abfd, ptr);
00839 
00840   flags = elf_elfheader (abfd)->e_flags;
00841   fprintf (file, _("private flags = 0x%lx:"), (long)flags);
00842 
00843   switch (flags & EF_IQ2000_CPU_MASK)
00844     {
00845     case EF_IQ2000_CPU_IQ10:
00846       fprintf (file, " -m10");
00847       break;
00848     case EF_IQ2000_CPU_IQ2000:
00849       fprintf (file, " -m2000");
00850       break;
00851     default:
00852       break;
00853     }
00854 
00855   fputc ('\n', file);
00856   return TRUE;
00857 }
00858 
00859 static
00860 bfd_boolean
00861 iq2000_elf_object_p (bfd *abfd)
00862 {
00863   bfd_default_set_arch_mach (abfd, bfd_arch_iq2000,
00864                           elf32_iq2000_machine (abfd));
00865   return TRUE;
00866 }
00867 
00868 
00869 #define ELF_ARCH            bfd_arch_iq2000
00870 #define ELF_MACHINE_CODE    EM_IQ2000
00871 #define ELF_MAXPAGESIZE            0x1000
00872 
00873 #define TARGET_BIG_SYM             bfd_elf32_iq2000_vec
00874 #define TARGET_BIG_NAME            "elf32-iq2000"
00875 
00876 #define elf_info_to_howto_rel                    NULL
00877 #define elf_info_to_howto                 iq2000_info_to_howto_rela
00878 #define elf_backend_relocate_section             iq2000_elf_relocate_section
00879 #define elf_backend_gc_mark_hook          iq2000_elf_gc_mark_hook
00880 #define elf_backend_check_relocs          iq2000_elf_check_relocs
00881 #define elf_backend_object_p                     iq2000_elf_object_p
00882 #define elf_backend_rela_normal                  1
00883 
00884 #define elf_backend_can_gc_sections              1
00885 
00886 #define bfd_elf32_bfd_reloc_type_lookup          iq2000_reloc_type_lookup
00887 #define bfd_elf32_bfd_reloc_name_lookup   iq2000_reloc_name_lookup
00888 #define bfd_elf32_bfd_set_private_flags          iq2000_elf_set_private_flags
00889 #define bfd_elf32_bfd_copy_private_bfd_data      iq2000_elf_copy_private_bfd_data
00890 #define bfd_elf32_bfd_merge_private_bfd_data     iq2000_elf_merge_private_bfd_data
00891 #define bfd_elf32_bfd_print_private_bfd_data     iq2000_elf_print_private_bfd_data
00892 
00893 #include "elf32-target.h"