Back to index

cell-binutils  2.17cvs20070401
elf32-mep.c
Go to the documentation of this file.
00001 /* MeP-specific support for 32-bit ELF.
00002    Copyright (C) 2001, 2002, 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/mep.h"
00026 #include "libiberty.h"
00027 
00028 /* Forward declarations.  */
00029 
00030 /* Private relocation functions.  */
00031 
00032 #define MEPREL(type, size, bits, right, left, pcrel, overflow, mask) \
00033   {(unsigned)type, right, size, bits, pcrel, left, overflow, mep_reloc, #type, FALSE, 0, mask, 0 }
00034 
00035 #define N complain_overflow_dont
00036 #define S complain_overflow_signed
00037 #define U complain_overflow_unsigned
00038 
00039 static bfd_reloc_status_type mep_reloc (bfd *, arelent *, struct bfd_symbol *,
00040                                    void *, asection *, bfd *, char **);
00041 
00042 static reloc_howto_type mep_elf_howto_table [] =
00043 {
00044   /* type, size, bits, leftshift, rightshift, pcrel, OD/OS/OU, mask.  */
00045   MEPREL (R_MEP_NONE,     0,  0, 0, 0, 0, N, 0),
00046   MEPREL (R_RELC,         0,  0, 0, 0, 0, N, 0),
00047   /* MEPRELOC:HOWTO */
00048     /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
00049   MEPREL (R_MEP_8,        0,  8, 0, 0, 0, U, 0xff),
00050   MEPREL (R_MEP_16,       1, 16, 0, 0, 0, U, 0xffff),
00051   MEPREL (R_MEP_32,       2, 32, 0, 0, 0, U, 0xffffffff),
00052   MEPREL (R_MEP_PCREL8A2, 1,  8, 1, 1, 1, S, 0x00fe),
00053   MEPREL (R_MEP_PCREL12A2,1, 12, 1, 1, 1, S, 0x0ffe),
00054   MEPREL (R_MEP_PCREL17A2,2, 17, 0, 1, 1, S, 0x0000ffff),
00055   MEPREL (R_MEP_PCREL24A2,2, 24, 0, 1, 1, S, 0x07f0ffff),
00056   MEPREL (R_MEP_PCABS24A2,2, 24, 0, 1, 0, U, 0x07f0ffff),
00057   MEPREL (R_MEP_LOW16,    2, 16, 0, 0, 0, N, 0x0000ffff),
00058   MEPREL (R_MEP_HI16U,    2, 32, 0,16, 0, N, 0x0000ffff),
00059   MEPREL (R_MEP_HI16S,    2, 32, 0,16, 0, N, 0x0000ffff),
00060   MEPREL (R_MEP_GPREL,    2, 16, 0, 0, 0, S, 0x0000ffff),
00061   MEPREL (R_MEP_TPREL,    2, 16, 0, 0, 0, S, 0x0000ffff),
00062   MEPREL (R_MEP_TPREL7,   1,  7, 0, 0, 0, U, 0x007f),
00063   MEPREL (R_MEP_TPREL7A2, 1,  7, 1, 1, 0, U, 0x007e),
00064   MEPREL (R_MEP_TPREL7A4, 1,  7, 2, 2, 0, U, 0x007c),
00065   MEPREL (R_MEP_UIMM24,   2, 24, 0, 0, 0, U, 0x00ffffff),
00066   MEPREL (R_MEP_ADDR24A4, 2, 24, 0, 2, 0, U, 0x00fcffff),
00067   MEPREL (R_MEP_GNU_VTINHERIT,1,  0,16,32, 0, N, 0x0000),
00068   MEPREL (R_MEP_GNU_VTENTRY,1,  0,16,32, 0, N, 0x0000),
00069   /* MEPRELOC:END */
00070 };
00071 
00072 #define VALID_MEP_RELOC(N) ((N) >= 0 \
00073   && (N) < ARRAY_SIZE (mep_elf_howto_table)
00074 
00075 #undef N
00076 #undef S
00077 #undef U
00078 
00079 static bfd_reloc_status_type
00080 mep_reloc
00081     (bfd *               abfd ATTRIBUTE_UNUSED,
00082      arelent *           reloc_entry ATTRIBUTE_UNUSED,
00083      struct bfd_symbol * symbol ATTRIBUTE_UNUSED,
00084      void *              data ATTRIBUTE_UNUSED,
00085      asection *          input_section ATTRIBUTE_UNUSED,
00086      bfd *               output_bfd ATTRIBUTE_UNUSED,
00087      char **             error_message ATTRIBUTE_UNUSED)
00088 {
00089   return bfd_reloc_ok;
00090 }
00091 
00092 
00093 
00094 #define BFD_RELOC_MEP_NONE BFD_RELOC_NONE
00095 #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
00096 #define MAP(n) case BFD_RELOC_MEP_##n: type = R_MEP_##n; break
00097 #else
00098 #define MAP(n) case BFD_RELOC_MEP_n: type = R_MEP_n; break
00099 #endif
00100 
00101 static reloc_howto_type *
00102 mep_reloc_type_lookup
00103     (bfd * abfd ATTRIBUTE_UNUSED,
00104      bfd_reloc_code_real_type code)
00105 {
00106   unsigned int type = 0;
00107 
00108   switch (code)
00109     {
00110     MAP(NONE);
00111     case BFD_RELOC_8:
00112       type = R_MEP_8;
00113       break;
00114     case BFD_RELOC_16:
00115       type = R_MEP_16;
00116       break;
00117     case BFD_RELOC_32:
00118       type = R_MEP_32;
00119       break;
00120     case BFD_RELOC_VTABLE_ENTRY:
00121       type = R_MEP_GNU_VTENTRY;
00122       break;
00123     case BFD_RELOC_VTABLE_INHERIT:
00124       type = R_MEP_GNU_VTINHERIT;
00125       break;
00126     case BFD_RELOC_RELC:
00127       type = R_RELC;
00128       break;
00129 
00130     /* MEPRELOC:MAP */
00131     /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
00132     MAP(8);
00133     MAP(16);
00134     MAP(32);
00135     MAP(PCREL8A2);
00136     MAP(PCREL12A2);
00137     MAP(PCREL17A2);
00138     MAP(PCREL24A2);
00139     MAP(PCABS24A2);
00140     MAP(LOW16);
00141     MAP(HI16U);
00142     MAP(HI16S);
00143     MAP(GPREL);
00144     MAP(TPREL);
00145     MAP(TPREL7);
00146     MAP(TPREL7A2);
00147     MAP(TPREL7A4);
00148     MAP(UIMM24);
00149     MAP(ADDR24A4);
00150     MAP(GNU_VTINHERIT);
00151     MAP(GNU_VTENTRY);
00152     /* MEPRELOC:END */
00153 
00154     default:
00155       /* Pacify gcc -Wall.  */
00156       fprintf (stderr, "mep: no reloc for code %d\n", code);
00157       return NULL;
00158     }
00159 
00160   if (mep_elf_howto_table[type].type != type)
00161     {
00162       fprintf (stderr, "MeP: howto %d has type %d\n", type, mep_elf_howto_table[type].type);
00163       abort ();
00164     }
00165 
00166   return mep_elf_howto_table + type;
00167 }
00168 
00169 #undef MAP
00170 
00171 static reloc_howto_type *
00172 mep_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
00173 {
00174   unsigned int i;
00175 
00176   for (i = 0;
00177        i < sizeof (mep_elf_howto_table) / sizeof (mep_elf_howto_table[0]);
00178        i++)
00179     if (mep_elf_howto_table[i].name != NULL
00180        && strcasecmp (mep_elf_howto_table[i].name, r_name) == 0)
00181       return &mep_elf_howto_table[i];
00182 
00183   return NULL;
00184 }
00185 
00186 /* Perform a single relocation.  */
00187 
00188 static struct bfd_link_info *mep_info;
00189 static int warn_tp = 0, warn_sda = 0;
00190 
00191 static bfd_vma
00192 mep_lookup_global
00193     (char *    name,
00194      bfd_vma   ofs,
00195      bfd_vma * cache,
00196      int *     warn)
00197 {
00198   struct bfd_link_hash_entry *h;
00199 
00200   if (*cache || *warn)
00201     return *cache;
00202 
00203   h = bfd_link_hash_lookup (mep_info->hash, name, FALSE, FALSE, TRUE);
00204   if (h == 0 || h->type != bfd_link_hash_defined)
00205     {
00206       *warn = ofs + 1;
00207       return 0;
00208     }
00209   *cache = (h->u.def.value
00210          + h->u.def.section->output_section->vma
00211          + h->u.def.section->output_offset);
00212   return *cache;
00213 }
00214 
00215 static bfd_vma
00216 mep_tpoff_base (bfd_vma ofs)
00217 {
00218   static bfd_vma cache = 0;
00219   return mep_lookup_global ("__tpbase", ofs, &cache, &warn_tp);
00220 }
00221 
00222 static bfd_vma
00223 mep_sdaoff_base (bfd_vma ofs)
00224 {
00225   static bfd_vma cache = 0;
00226   return mep_lookup_global ("__sdabase", ofs, &cache, &warn_sda);
00227 }
00228 
00229 static bfd_reloc_status_type
00230 mep_final_link_relocate
00231     (reloc_howto_type *  howto,
00232      bfd *               input_bfd,
00233      asection *          input_section,
00234      bfd_byte *          contents,
00235      Elf_Internal_Rela * rel,
00236      bfd_vma             relocation)
00237 {
00238   unsigned long u;
00239   long s;
00240   unsigned char *byte;
00241   bfd_vma pc;
00242   bfd_reloc_status_type r = bfd_reloc_ok;
00243   int e2, e4;
00244 
00245   if (bfd_big_endian (input_bfd))
00246     {
00247       e2 = 0;
00248       e4 = 0;
00249     }
00250   else
00251     {
00252       e2 = 1;
00253       e4 = 3;
00254     }
00255 
00256   pc = (input_section->output_section->vma
00257        + input_section->output_offset
00258        + rel->r_offset);
00259 
00260   s = relocation + rel->r_addend;
00261 
00262   byte = (unsigned char *)contents + rel->r_offset;
00263 
00264   if (howto->type == R_MEP_PCREL24A2
00265       && s == 0
00266       && pc >= 0x800000)
00267     {
00268       /* This is an unreachable branch to an undefined weak function.
00269         Silently ignore it, since the opcode can't do that but should
00270         never be executed anyway.  */
00271       return bfd_reloc_ok;
00272     }
00273 
00274   if (howto->pc_relative)
00275     s -= pc;
00276 
00277   u = (unsigned long) s;
00278 
00279   switch (howto->type)
00280     {
00281     /* MEPRELOC:APPLY */
00282     /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
00283     case R_MEP_8: /* 76543210 */
00284       if (u > 255) r = bfd_reloc_overflow;
00285       byte[0] = (u & 0xff);
00286       break;
00287     case R_MEP_16: /* fedcba9876543210 */
00288       if (u > 65535) r = bfd_reloc_overflow;
00289       byte[0^e2] = ((u >> 8) & 0xff);
00290       byte[1^e2] = (u & 0xff);
00291       break;
00292     case R_MEP_32: /* vutsrqponmlkjihgfedcba9876543210 */
00293       byte[0^e4] = ((u >> 24) & 0xff);
00294       byte[1^e4] = ((u >> 16) & 0xff);
00295       byte[2^e4] = ((u >> 8) & 0xff);
00296       byte[3^e4] = (u & 0xff);
00297       break;
00298     case R_MEP_PCREL8A2: /* --------7654321- */
00299       if (-128 > s || s > 127) r = bfd_reloc_overflow;
00300       byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
00301       break;
00302     case R_MEP_PCREL12A2: /* ----ba987654321- */
00303       if (-2048 > s || s > 2047) r = bfd_reloc_overflow;
00304       byte[0^e2] = (byte[0^e2] & 0xf0) | ((s >> 8) & 0x0f);
00305       byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
00306       break;
00307     case R_MEP_PCREL17A2: /* ----------------gfedcba987654321 */
00308       if (-65536 > s || s > 65535) r = bfd_reloc_overflow;
00309       byte[2^e2] = ((s >> 9) & 0xff);
00310       byte[3^e2] = ((s >> 1) & 0xff);
00311       break;
00312     case R_MEP_PCREL24A2: /* -----7654321----nmlkjihgfedcba98 */
00313       if (-8388608 > s || s > 8388607) r = bfd_reloc_overflow;
00314       byte[0^e2] = (byte[0^e2] & 0xf8) | ((s >> 5) & 0x07);
00315       byte[1^e2] = (byte[1^e2] & 0x0f) | ((s << 3) & 0xf0);
00316       byte[2^e2] = ((s >> 16) & 0xff);
00317       byte[3^e2] = ((s >> 8) & 0xff);
00318       break;
00319     case R_MEP_PCABS24A2: /* -----7654321----nmlkjihgfedcba98 */
00320       if (u > 16777215) r = bfd_reloc_overflow;
00321       byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
00322       byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
00323       byte[2^e2] = ((u >> 16) & 0xff);
00324       byte[3^e2] = ((u >> 8) & 0xff);
00325       break;
00326     case R_MEP_LOW16: /* ----------------fedcba9876543210 */
00327       byte[2^e2] = ((u >> 8) & 0xff);
00328       byte[3^e2] = (u & 0xff);
00329       break;
00330     case R_MEP_HI16U: /* ----------------vutsrqponmlkjihg */
00331       byte[2^e2] = ((u >> 24) & 0xff);
00332       byte[3^e2] = ((u >> 16) & 0xff);
00333       break;
00334     case R_MEP_HI16S: /* ----------------vutsrqponmlkjihg */
00335       byte[2^e2] = ((s >> 24) & 0xff);
00336       byte[3^e2] = ((s >> 16) & 0xff);
00337       break;
00338     case R_MEP_GPREL: /* ----------------fedcba9876543210 */
00339       s -= mep_sdaoff_base(rel->r_offset);
00340       if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
00341       byte[2^e2] = ((s >> 8) & 0xff);
00342       byte[3^e2] = (s & 0xff);
00343       break;
00344     case R_MEP_TPREL: /* ----------------fedcba9876543210 */
00345       s -= mep_tpoff_base(rel->r_offset);
00346       if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
00347       byte[2^e2] = ((s >> 8) & 0xff);
00348       byte[3^e2] = (s & 0xff);
00349       break;
00350     case R_MEP_TPREL7: /* ---------6543210 */
00351       u -= mep_tpoff_base(rel->r_offset);
00352       if (u > 127) r = bfd_reloc_overflow;
00353       byte[1^e2] = (byte[1^e2] & 0x80) | (u & 0x7f);
00354       break;
00355     case R_MEP_TPREL7A2: /* ---------654321- */
00356       u -= mep_tpoff_base(rel->r_offset);
00357       if (u > 127) r = bfd_reloc_overflow;
00358       byte[1^e2] = (byte[1^e2] & 0x81) | (u & 0x7e);
00359       break;
00360     case R_MEP_TPREL7A4: /* ---------65432-- */
00361       u -= mep_tpoff_base(rel->r_offset);
00362       if (u > 127) r = bfd_reloc_overflow;
00363       byte[1^e2] = (byte[1^e2] & 0x83) | (u & 0x7c);
00364       break;
00365     case R_MEP_UIMM24: /* --------76543210nmlkjihgfedcba98 */
00366       if (u > 16777215) r = bfd_reloc_overflow;
00367       byte[1^e2] = (u & 0xff);
00368       byte[2^e2] = ((u >> 16) & 0xff);
00369       byte[3^e2] = ((u >> 8) & 0xff);
00370       break;
00371     case R_MEP_ADDR24A4: /* --------765432--nmlkjihgfedcba98 */
00372       if (u > 16777215) r = bfd_reloc_overflow;
00373       byte[1^e2] = (byte[1^e2] & 0x03) | (u & 0xfc);
00374       byte[2^e2] = ((u >> 16) & 0xff);
00375       byte[3^e2] = ((u >> 8) & 0xff);
00376       break;
00377     case R_MEP_GNU_VTINHERIT: /* ---------------- */
00378       break;
00379     case R_MEP_GNU_VTENTRY: /* ---------------- */
00380       break;
00381     /* MEPRELOC:END */
00382     default:
00383       abort ();
00384     }
00385 
00386   return r;
00387 }
00388 
00389 /* Set the howto pointer for a MEP ELF reloc.  */
00390 
00391 static void
00392 mep_info_to_howto_rela
00393     (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   cache_ptr->howto = & mep_elf_howto_table [r_type];
00401 }
00402 
00403 /* Look through the relocs for a section during the first phase.
00404    Since we don't do .gots or .plts, we just need to consider the
00405    virtual table relocs for gc.  */
00406 
00407 static bfd_boolean
00408 mep_elf_check_relocs
00409     (bfd *                     abfd,
00410      struct bfd_link_info *    info,
00411      asection *                sec,
00412      const Elf_Internal_Rela * relocs)
00413 {
00414   Elf_Internal_Shdr *           symtab_hdr;
00415   struct elf_link_hash_entry ** sym_hashes;
00416   struct elf_link_hash_entry ** sym_hashes_end;
00417   const Elf_Internal_Rela *     rel;
00418   const Elf_Internal_Rela *     rel_end;
00419 
00420   if (info->relocatable)
00421     return TRUE;
00422 
00423   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00424   sym_hashes = elf_sym_hashes (abfd);
00425   sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
00426   if (!elf_bad_symtab (abfd))
00427     sym_hashes_end -= symtab_hdr->sh_info;
00428 
00429   rel_end = relocs + sec->reloc_count;
00430   for (rel = relocs; rel < rel_end; rel++)
00431     {
00432       struct elf_link_hash_entry *h;
00433       unsigned long r_symndx;
00434 
00435       r_symndx = ELF32_R_SYM (rel->r_info);
00436       if (r_symndx < symtab_hdr->sh_info)
00437         h = NULL;
00438       else
00439         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
00440     }
00441   return TRUE;
00442 }
00443 
00444 
00445 /* Relocate a MEP ELF section.
00446    There is some attempt to make this function usable for many architectures,
00447    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
00448    if only to serve as a learning tool.
00449 
00450    The RELOCATE_SECTION function is called by the new ELF backend linker
00451    to handle the relocations for a section.
00452 
00453    The relocs are always passed as Rela structures; if the section
00454    actually uses Rel structures, the r_addend field will always be
00455    zero.
00456 
00457    This function is responsible for adjusting the section contents as
00458    necessary, and (if using Rela relocs and generating a relocatable
00459    output file) adjusting the reloc addend as necessary.
00460 
00461    This function does not have to worry about setting the reloc
00462    address or the reloc symbol index.
00463 
00464    LOCAL_SYMS is a pointer to the swapped in local symbols.
00465 
00466    LOCAL_SECTIONS is an array giving the section in the input file
00467    corresponding to the st_shndx field of each local symbol.
00468 
00469    The global hash table entry for the global symbols can be found
00470    via elf_sym_hashes (input_bfd).
00471 
00472    When generating relocatable output, this function must handle
00473    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
00474    going to be the section symbol corresponding to the output
00475    section, which means that the addend must be adjusted
00476    accordingly.  */
00477 
00478 static bfd_boolean
00479 mep_elf_relocate_section
00480     (bfd *                   output_bfd ATTRIBUTE_UNUSED,
00481      struct bfd_link_info *  info,
00482      bfd *                   input_bfd,
00483      asection *              input_section,
00484      bfd_byte *              contents,
00485      Elf_Internal_Rela *     relocs,
00486      Elf_Internal_Sym *      local_syms,
00487      asection **             local_sections)
00488 {
00489   Elf_Internal_Shdr *           symtab_hdr;
00490   struct elf_link_hash_entry ** sym_hashes;
00491   Elf_Internal_Rela *           rel;
00492   Elf_Internal_Rela *           relend;
00493 
00494   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
00495   sym_hashes = elf_sym_hashes (input_bfd);
00496   relend     = relocs + input_section->reloc_count;
00497 
00498   mep_info = info;
00499 
00500   for (rel = relocs; rel < relend; rel ++)
00501     {
00502       reloc_howto_type *           howto;
00503       unsigned long                r_symndx;
00504       Elf_Internal_Sym *           sym;
00505       asection *                   sec;
00506       struct elf_link_hash_entry * h;
00507       bfd_vma                      relocation;
00508       bfd_reloc_status_type        r;
00509       const char *                 name = NULL;
00510       int                          r_type;
00511 
00512       r_type = ELF32_R_TYPE (rel->r_info);
00513 
00514       r_symndx = ELF32_R_SYM (rel->r_info);
00515 
00516       /* Is this a complex relocation?  */
00517       if (!info->relocatable && ELF32_R_TYPE (rel->r_info) == R_RELC)
00518        {
00519          bfd_elf_perform_complex_relocation (output_bfd, info,
00520                                          input_bfd, input_section, contents,
00521                                          rel, local_syms, local_sections);
00522          continue;
00523        }
00524 
00525       howto  = mep_elf_howto_table + ELF32_R_TYPE (rel->r_info);
00526       h      = NULL;
00527       sym    = NULL;
00528       sec    = NULL;
00529 
00530       if (r_symndx < symtab_hdr->sh_info)
00531        {
00532          sym = local_syms + r_symndx;
00533          sec = local_sections [r_symndx];
00534          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
00535 
00536          name = bfd_elf_string_from_elf_section
00537            (input_bfd, symtab_hdr->sh_link, sym->st_name);
00538          name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
00539 #if 0
00540          fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
00541                  sec->name, name, sym->st_name,
00542                  sec->output_section->vma, sec->output_offset,
00543                  sym->st_value, rel->r_addend);
00544 #endif
00545        }
00546       else
00547        {
00548          relocation = 0;
00549          h = sym_hashes [r_symndx];
00550 
00551          while (h->root.type == bfd_link_hash_indirect
00552                || h->root.type == bfd_link_hash_warning)
00553            h = (struct elf_link_hash_entry *) h->root.u.i.link;
00554 
00555          name = h->root.root.string;
00556 
00557          if (h->root.type == bfd_link_hash_defined
00558              || h->root.type == bfd_link_hash_defweak)
00559            {
00560              sec = h->root.u.def.section;
00561              relocation = (h->root.u.def.value
00562                          + sec->output_section->vma
00563                          + sec->output_offset);
00564 #if 0
00565              fprintf (stderr,
00566                      "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
00567                      sec->name, name, h->root.u.def.value,
00568                      sec->output_section->vma, sec->output_offset, relocation);
00569 #endif
00570            }
00571          else if (h->root.type == bfd_link_hash_undefweak)
00572            {
00573 #if 0
00574              fprintf (stderr, "undefined: sec: %s, name: %s\n",
00575                      sec->name, name);
00576 #endif
00577            }
00578          else if (!info->relocatable)
00579            {
00580              if (! ((*info->callbacks->undefined_symbol)
00581                    (info, h->root.root.string, input_bfd,
00582                     input_section, rel->r_offset,
00583                     (!info->shared && info->unresolved_syms_in_objects == RM_GENERATE_ERROR))))
00584               return FALSE;
00585 #if 0
00586              fprintf (stderr, "unknown: name: %s\n", name);
00587 #endif
00588            }
00589        }
00590 
00591       if (sec != NULL && elf_discarded_section (sec))
00592        {
00593          /* For relocs against symbols from removed linkonce sections,
00594             or sections discarded by a linker script, we just want the
00595             section contents zeroed.  Avoid any special processing.  */
00596          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
00597          rel->r_info = 0;
00598          rel->r_addend = 0;
00599          continue;
00600        }
00601 
00602       if (info->relocatable)
00603        {
00604          /* This is a relocatable link.  We don't have to change
00605              anything, unless the reloc is against a section symbol,
00606              in which case we have to adjust according to where the
00607              section symbol winds up in the output section.  */
00608          if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
00609            rel->r_addend += sec->output_offset;
00610          continue;
00611        }
00612 
00613       switch (r_type)
00614        {
00615        default:
00616          r = mep_final_link_relocate (howto, input_bfd, input_section,
00617                                     contents, rel, relocation);
00618          break;
00619        }
00620 
00621       if (r != bfd_reloc_ok)
00622        {
00623          const char * msg = (const char *) NULL;
00624 
00625          switch (r)
00626            {
00627            case bfd_reloc_overflow:
00628              r = info->callbacks->reloc_overflow
00629               (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
00630                input_bfd, input_section, rel->r_offset);
00631              break;
00632 
00633            case bfd_reloc_undefined:
00634              r = info->callbacks->undefined_symbol
00635               (info, name, input_bfd, input_section, rel->r_offset, TRUE);
00636              break;
00637 
00638            case bfd_reloc_outofrange:
00639              msg = _("internal error: out of range error");
00640              break;
00641 
00642            case bfd_reloc_notsupported:
00643              msg = _("internal error: unsupported relocation error");
00644              break;
00645 
00646            case bfd_reloc_dangerous:
00647              msg = _("internal error: dangerous relocation");
00648              break;
00649 
00650            default:
00651              msg = _("internal error: unknown error");
00652              break;
00653            }
00654 
00655          if (msg)
00656            r = info->callbacks->warning
00657              (info, msg, name, input_bfd, input_section, rel->r_offset);
00658 
00659          if (! r)
00660            return FALSE;
00661        }
00662     }
00663 
00664   if (warn_tp)
00665     info->callbacks->undefined_symbol
00666       (info, "__tpbase", input_bfd, input_section, warn_tp-1, TRUE);
00667   if (warn_sda)
00668     info->callbacks->undefined_symbol
00669       (info, "__sdabase", input_bfd, input_section, warn_sda-1, TRUE);
00670   if (warn_sda || warn_tp)
00671     return FALSE;
00672 
00673   return TRUE;
00674 }
00675 
00676 
00677 /* Update the got entry reference counts for the section being
00678    removed.  */
00679 
00680 static bfd_boolean
00681 mep_elf_gc_sweep_hook
00682     (bfd *                     abfd ATTRIBUTE_UNUSED,
00683      struct bfd_link_info *    info ATTRIBUTE_UNUSED,
00684      asection *                sec ATTRIBUTE_UNUSED,
00685      const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)
00686 {
00687   return TRUE;
00688 }
00689 
00690 /* Return the section that should be marked against GC for a given
00691    relocation.  */
00692 
00693 static asection *
00694 mep_elf_gc_mark_hook
00695     (asection *                   sec,
00696      struct bfd_link_info *       info ATTRIBUTE_UNUSED,
00697      Elf_Internal_Rela *          rel,
00698      struct elf_link_hash_entry * h,
00699      Elf_Internal_Sym *           sym)
00700 {
00701   if (h != NULL)
00702     {
00703       switch (ELF32_R_TYPE (rel->r_info))
00704        {
00705        default:
00706          switch (h->root.type)
00707            {
00708            case bfd_link_hash_defined:
00709            case bfd_link_hash_defweak:
00710              return h->root.u.def.section;
00711 
00712            case bfd_link_hash_common:
00713              return h->root.u.c.p->section;
00714 
00715            default:
00716              break;
00717            }
00718        }
00719     }
00720   else
00721     {
00722       if (!(elf_bad_symtab (sec->owner)
00723            && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
00724          && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
00725               && sym->st_shndx != SHN_COMMON))
00726        return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
00727     }
00728 
00729   return NULL;
00730 }
00731 
00732 
00733 /* Function to set the ELF flag bits.  */
00734 
00735 static bfd_boolean
00736 mep_elf_set_private_flags (bfd *    abfd,
00737                         flagword flags)
00738 {
00739   elf_elfheader (abfd)->e_flags = flags;
00740   elf_flags_init (abfd) = TRUE;
00741   return TRUE;
00742 }
00743 
00744 static bfd_boolean
00745 mep_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
00746 {
00747   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
00748       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
00749     return TRUE;
00750 
00751   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
00752   elf_flags_init (obfd) = TRUE;
00753   return TRUE;
00754 }
00755 
00756 /* Merge backend specific data from an object file to the output
00757    object file when linking.  */
00758 
00759 static bfd_boolean
00760 mep_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
00761 {
00762   static bfd *last_ibfd = 0;
00763   flagword old_flags, new_flags;
00764   flagword old_partial, new_partial;
00765 
00766   /* Check if we have the same endianess.  */
00767   if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
00768     return FALSE;
00769 
00770   new_flags = elf_elfheader (ibfd)->e_flags;
00771   old_flags = elf_elfheader (obfd)->e_flags;
00772 
00773 #ifdef DEBUG
00774   _bfd_error_handler ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s",
00775                     ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
00776 #endif
00777 
00778     /* First call, no flags set.  */
00779     if (!elf_flags_init (obfd))
00780     {
00781       elf_flags_init (obfd) = TRUE;
00782       old_flags = new_flags;
00783     }
00784   else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
00785     {
00786       /* Non-library flags trump library flags.  The choice doesn't really
00787         matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
00788       if (old_flags & EF_MEP_LIBRARY)
00789        old_flags = new_flags;
00790     }
00791   else
00792     {
00793       /* Make sure they're for the same mach.  Allow upgrade from the "mep"
00794         mach.  */
00795       new_partial = (new_flags & EF_MEP_CPU_MASK);
00796       old_partial = (old_flags & EF_MEP_CPU_MASK);
00797       if (new_partial == old_partial)
00798        ;
00799       else if (new_partial == EF_MEP_CPU_MEP)
00800        ;
00801       else if (old_partial == EF_MEP_CPU_MEP)
00802        old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
00803       else
00804        {
00805          _bfd_error_handler (_("%B and %B are for different cores"), last_ibfd, ibfd);
00806          bfd_set_error (bfd_error_invalid_target);
00807          return FALSE;
00808        }
00809 
00810       /* Make sure they're for the same me_module.  Allow basic config to
00811         mix with any other.  */
00812       new_partial = (new_flags & EF_MEP_INDEX_MASK);
00813       old_partial = (old_flags & EF_MEP_INDEX_MASK);
00814       if (new_partial == old_partial)
00815        ;
00816       else if (new_partial == 0)
00817        ;
00818       else if (old_partial == 0)
00819        old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
00820       else
00821        {
00822          _bfd_error_handler (_("%B and %B are for different configurations"), last_ibfd, ibfd);
00823          bfd_set_error (bfd_error_invalid_target);
00824          return FALSE;
00825        }
00826     }
00827 
00828   elf_elfheader (obfd)->e_flags = old_flags;
00829   last_ibfd = ibfd;
00830   return TRUE;
00831 }
00832 
00833 /* This will be edited by the MeP configration tool.  */
00834 static const char * config_names[] =
00835 {
00836   "basic"
00837   /* start-mepcfgtool */
00838   ,"simple"
00839   ,"fmax"
00840   /* end-mepcfgtool */
00841 };
00842 
00843 static const char * core_names[] =
00844 {
00845   "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
00846 };
00847 
00848 static bfd_boolean
00849 mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
00850 {
00851   FILE *   file = (FILE *) ptr;
00852   flagword flags, partial_flags;
00853 
00854   BFD_ASSERT (abfd != NULL && ptr != NULL);
00855 
00856   /* Print normal ELF private data.  */
00857   _bfd_elf_print_private_bfd_data (abfd, ptr);
00858 
00859   flags = elf_elfheader (abfd)->e_flags;
00860   fprintf (file, _("private flags = 0x%lx"), (long)flags);
00861 
00862   partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
00863   if (partial_flags < ARRAY_SIZE (core_names))
00864     fprintf (file, "  core: %s", core_names[(long)partial_flags]);
00865 
00866   partial_flags = flags & EF_MEP_INDEX_MASK;
00867   if (partial_flags < ARRAY_SIZE (config_names))
00868     fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);
00869 
00870   fputc ('\n', file);
00871 
00872   return TRUE;
00873 }
00874 
00875 /* Return the machine subcode from the ELF e_flags header.  */
00876 
00877 static int
00878 elf32_mep_machine (bfd * abfd)
00879 {
00880   switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
00881     {
00882     default: break;
00883     case EF_MEP_CPU_C2: return bfd_mach_mep;
00884     case EF_MEP_CPU_C3: return bfd_mach_mep;
00885     case EF_MEP_CPU_C4: return bfd_mach_mep;
00886     case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
00887     }
00888 
00889   return bfd_mach_mep;
00890 }
00891 
00892 static bfd_boolean
00893 mep_elf_object_p (bfd * abfd)
00894 {
00895   /* Irix 5 and 6 is broken.  Object file symbol tables are not always
00896      sorted correctly such that local symbols preceed global symbols,
00897      and the sh_info field in the symbol table is not always right.  */
00898   /* This is needed for the RELC support code.  */
00899   elf_bad_symtab (abfd) = TRUE;
00900   bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
00901   return TRUE;
00902 }
00903 
00904 static bfd_boolean
00905 mep_elf_section_flags (flagword * flags, const Elf_Internal_Shdr * hdr)
00906 {
00907   if (hdr->sh_flags & SHF_MEP_VLIW)
00908     * flags |= SEC_MEP_VLIW;
00909   return TRUE;
00910 }
00911 
00912 static bfd_boolean
00913 mep_elf_fake_sections (bfd *               abfd ATTRIBUTE_UNUSED,
00914                      Elf_Internal_Shdr * hdr,
00915                      asection *          sec)
00916 {
00917   if (sec->flags & SEC_MEP_VLIW)
00918     hdr->sh_flags |= SHF_MEP_VLIW;
00919   return TRUE;
00920 }
00921 
00922 
00923 #define ELF_ARCH            bfd_arch_mep
00924 #define ELF_MACHINE_CODE    EM_CYGNUS_MEP
00925 #define ELF_MAXPAGESIZE            0x1000
00926 
00927 #define TARGET_BIG_SYM             bfd_elf32_mep_vec
00928 #define TARGET_BIG_NAME            "elf32-mep"
00929 
00930 #define TARGET_LITTLE_SYM   bfd_elf32_mep_little_vec
00931 #define TARGET_LITTLE_NAME  "elf32-mep-little"
00932 
00933 #define elf_info_to_howto_rel                    NULL
00934 #define elf_info_to_howto                 mep_info_to_howto_rela
00935 #define elf_backend_relocate_section             mep_elf_relocate_section
00936 #define elf_backend_gc_mark_hook          mep_elf_gc_mark_hook
00937 #define elf_backend_gc_sweep_hook         mep_elf_gc_sweep_hook
00938 #define elf_backend_check_relocs                mep_elf_check_relocs
00939 #define elf_backend_object_p                      mep_elf_object_p
00940 #define elf_backend_section_flags         mep_elf_section_flags
00941 #define elf_backend_fake_sections         mep_elf_fake_sections
00942 
00943 #define elf_backend_can_gc_sections              1
00944 
00945 #define bfd_elf32_bfd_reloc_type_lookup          mep_reloc_type_lookup
00946 #define bfd_elf32_bfd_reloc_name_lookup   mep_reloc_name_lookup
00947 #define bfd_elf32_bfd_set_private_flags          mep_elf_set_private_flags
00948 #define bfd_elf32_bfd_copy_private_bfd_data      mep_elf_copy_private_bfd_data
00949 #define bfd_elf32_bfd_merge_private_bfd_data     mep_elf_merge_private_bfd_data
00950 #define bfd_elf32_bfd_print_private_bfd_data     mep_elf_print_private_bfd_data
00951 
00952 /* We use only the RELA entries.  */
00953 #define USE_RELA
00954 
00955 #include "elf32-target.h"