(root)/
binutils-2.41/
bfd/
elf32-mep.c
       1  /* MeP-specific support for 32-bit ELF.
       2     Copyright (C) 2001-2023 Free Software Foundation, Inc.
       3  
       4     This file is part of BFD, the Binary File Descriptor library.
       5  
       6     This program is free software; you can redistribute it and/or modify
       7     it under the terms of the GNU General Public License as published by
       8     the Free Software Foundation; either version 3 of the License, or
       9     (at your option) any later version.
      10  
      11     This program is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14     GNU General Public License for more details.
      15  
      16     You should have received a copy of the GNU General Public License
      17     along with this program; if not, write to the Free Software
      18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      19     MA 02110-1301, USA.  */
      20  
      21  #include "sysdep.h"
      22  #include "bfd.h"
      23  #include "libbfd.h"
      24  #include "elf-bfd.h"
      25  #include "elf/mep.h"
      26  #include "libiberty.h"
      27  
      28  /* Forward declarations.  */
      29  
      30  /* Private relocation functions.  */
      31  
      32  #define MEPREL(type, size, bits, right, left, pcrel, overflow, mask) \
      33    HOWTO (type, right, size, bits, pcrel, left, overflow, bfd_elf_generic_reloc, #type, false, 0, mask, 0)
      34  
      35  #define N complain_overflow_dont
      36  #define S complain_overflow_signed
      37  #define U complain_overflow_unsigned
      38  
      39  static reloc_howto_type mep_elf_howto_table [] =
      40  {
      41    /* type, size, bits, leftshift, rightshift, pcrel, OD/OS/OU, mask.  */
      42    MEPREL (R_MEP_NONE,	  0,  0, 0, 0, 0, N, 0),
      43    MEPREL (R_RELC,	  0,  0, 0, 0, 0, N, 0),
      44    /* MEPRELOC:HOWTO */
      45      /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
      46    MEPREL (R_MEP_8,        1,  8, 0, 0, 0, U, 0xff),
      47    MEPREL (R_MEP_16,       2, 16, 0, 0, 0, U, 0xffff),
      48    MEPREL (R_MEP_32,       4, 32, 0, 0, 0, U, 0xffffffff),
      49    MEPREL (R_MEP_PCREL8A2, 2,  8, 1, 1, 1, S, 0x00fe),
      50    MEPREL (R_MEP_PCREL12A2,2, 12, 1, 1, 1, S, 0x0ffe),
      51    MEPREL (R_MEP_PCREL17A2,4, 17, 0, 1, 1, S, 0x0000ffff),
      52    MEPREL (R_MEP_PCREL24A2,4, 24, 0, 1, 1, S, 0x07f0ffff),
      53    MEPREL (R_MEP_PCABS24A2,4, 24, 0, 1, 0, U, 0x07f0ffff),
      54    MEPREL (R_MEP_LOW16,    4, 16, 0, 0, 0, N, 0x0000ffff),
      55    MEPREL (R_MEP_HI16U,    4, 32, 0,16, 0, N, 0x0000ffff),
      56    MEPREL (R_MEP_HI16S,    4, 32, 0,16, 0, N, 0x0000ffff),
      57    MEPREL (R_MEP_GPREL,    4, 16, 0, 0, 0, S, 0x0000ffff),
      58    MEPREL (R_MEP_TPREL,    4, 16, 0, 0, 0, S, 0x0000ffff),
      59    MEPREL (R_MEP_TPREL7,   2,  7, 0, 0, 0, U, 0x007f),
      60    MEPREL (R_MEP_TPREL7A2, 2,  7, 1, 1, 0, U, 0x007e),
      61    MEPREL (R_MEP_TPREL7A4, 2,  7, 2, 2, 0, U, 0x007c),
      62    MEPREL (R_MEP_UIMM24,   4, 24, 0, 0, 0, U, 0x00ffffff),
      63    MEPREL (R_MEP_ADDR24A4, 4, 24, 0, 2, 0, U, 0x00fcffff),
      64    MEPREL (R_MEP_GNU_VTINHERIT,2,  0,16,32, 0, N, 0x0000),
      65    MEPREL (R_MEP_GNU_VTENTRY,2,  0,16,32, 0, N, 0x0000),
      66    /* MEPRELOC:END */
      67  };
      68  
      69  #define VALID_MEP_RELOC(N) ((N) >= 0 \
      70    && (N) < ARRAY_SIZE (mep_elf_howto_table)
      71  
      72  #undef N
      73  #undef S
      74  #undef U
      75  
      76  
      77  #define BFD_RELOC_MEP_NONE BFD_RELOC_NONE
      78  #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
      79  #define MAP(n) case BFD_RELOC_MEP_##n: type = R_MEP_##n; break
      80  #else
      81  #define MAP(n) case BFD_RELOC_MEP_/**/n: type = R_MEP_/**/n; break
      82  #endif
      83  
      84  static reloc_howto_type *
      85  mep_reloc_type_lookup
      86      (bfd * abfd ATTRIBUTE_UNUSED,
      87       bfd_reloc_code_real_type code)
      88  {
      89    unsigned int type = 0;
      90  
      91    switch (code)
      92      {
      93      MAP(NONE);
      94      case BFD_RELOC_8:
      95        type = R_MEP_8;
      96        break;
      97      case BFD_RELOC_16:
      98        type = R_MEP_16;
      99        break;
     100      case BFD_RELOC_32:
     101        type = R_MEP_32;
     102        break;
     103      case BFD_RELOC_VTABLE_ENTRY:
     104        type = R_MEP_GNU_VTENTRY;
     105        break;
     106      case BFD_RELOC_VTABLE_INHERIT:
     107        type = R_MEP_GNU_VTINHERIT;
     108        break;
     109      case BFD_RELOC_RELC:
     110        type = R_RELC;
     111        break;
     112  
     113      /* MEPRELOC:MAP */
     114      /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
     115      MAP(8);
     116      MAP(16);
     117      MAP(32);
     118      MAP(PCREL8A2);
     119      MAP(PCREL12A2);
     120      MAP(PCREL17A2);
     121      MAP(PCREL24A2);
     122      MAP(PCABS24A2);
     123      MAP(LOW16);
     124      MAP(HI16U);
     125      MAP(HI16S);
     126      MAP(GPREL);
     127      MAP(TPREL);
     128      MAP(TPREL7);
     129      MAP(TPREL7A2);
     130      MAP(TPREL7A4);
     131      MAP(UIMM24);
     132      MAP(ADDR24A4);
     133      MAP(GNU_VTINHERIT);
     134      MAP(GNU_VTENTRY);
     135      /* MEPRELOC:END */
     136  
     137      default:
     138        /* Pacify gcc -Wall.  */
     139        _bfd_error_handler (_("mep: no reloc for code %d"), code);
     140        return NULL;
     141      }
     142  
     143    if (mep_elf_howto_table[type].type != type)
     144      {
     145        /* xgettext:c-format */
     146        _bfd_error_handler (_("MeP: howto %d has type %d"),
     147  			  type, mep_elf_howto_table[type].type);
     148        abort ();
     149      }
     150  
     151    return mep_elf_howto_table + type;
     152  }
     153  
     154  #undef MAP
     155  
     156  static reloc_howto_type *
     157  mep_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
     158  {
     159    unsigned int i;
     160  
     161    for (i = 0;
     162         i < sizeof (mep_elf_howto_table) / sizeof (mep_elf_howto_table[0]);
     163         i++)
     164      if (mep_elf_howto_table[i].name != NULL
     165  	&& strcasecmp (mep_elf_howto_table[i].name, r_name) == 0)
     166        return &mep_elf_howto_table[i];
     167  
     168    return NULL;
     169  }
     170  
     171  /* Perform a single relocation.  */
     172  
     173  static struct bfd_link_info *mep_info;
     174  static int warn_tp = 0, warn_sda = 0;
     175  
     176  static bfd_vma
     177  mep_lookup_global
     178      (char *    name,
     179       bfd_vma   ofs,
     180       bfd_vma * cache,
     181       int *     warn)
     182  {
     183    struct bfd_link_hash_entry *h;
     184  
     185    if (*cache || *warn)
     186      return *cache;
     187  
     188    h = bfd_link_hash_lookup (mep_info->hash, name, false, false, true);
     189    if (h == 0 || h->type != bfd_link_hash_defined)
     190      {
     191        *warn = ofs + 1;
     192        return 0;
     193      }
     194    *cache = (h->u.def.value
     195  	  + h->u.def.section->output_section->vma
     196  	  + h->u.def.section->output_offset);
     197    return *cache;
     198  }
     199  
     200  static bfd_vma
     201  mep_tpoff_base (bfd_vma ofs)
     202  {
     203    static bfd_vma cache = 0;
     204    return mep_lookup_global ("__tpbase", ofs, &cache, &warn_tp);
     205  }
     206  
     207  static bfd_vma
     208  mep_sdaoff_base (bfd_vma ofs)
     209  {
     210    static bfd_vma cache = 0;
     211    return mep_lookup_global ("__sdabase", ofs, &cache, &warn_sda);
     212  }
     213  
     214  static bfd_reloc_status_type
     215  mep_final_link_relocate
     216      (reloc_howto_type *	 howto,
     217       bfd *		 input_bfd,
     218       asection *		 input_section,
     219       bfd_byte *		 contents,
     220       Elf_Internal_Rela * rel,
     221       bfd_vma		 relocation)
     222  {
     223    unsigned long u;
     224    unsigned char *byte;
     225    bfd_vma pc;
     226    bfd_reloc_status_type r = bfd_reloc_ok;
     227    int e2, e4;
     228  
     229    if (bfd_big_endian (input_bfd))
     230      {
     231        e2 = 0;
     232        e4 = 0;
     233      }
     234    else
     235      {
     236        e2 = 1;
     237        e4 = 3;
     238      }
     239  
     240    pc = (input_section->output_section->vma
     241  	+ input_section->output_offset
     242  	+ rel->r_offset);
     243  
     244    u = relocation + rel->r_addend;
     245  
     246    byte = (unsigned char *)contents + rel->r_offset;
     247  
     248    if (howto->type == R_MEP_PCREL24A2
     249        && u == 0
     250        && pc >= 0x800000)
     251      {
     252        /* This is an unreachable branch to an undefined weak function.
     253  	 Silently ignore it, since the opcode can't do that but should
     254  	 never be executed anyway.  */
     255        return bfd_reloc_ok;
     256      }
     257  
     258    if (howto->pc_relative)
     259      u -= pc;
     260  
     261    switch (howto->type)
     262      {
     263      /* MEPRELOC:APPLY */
     264      /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
     265      case R_MEP_8: /* 76543210 */
     266        if (u > 255) r = bfd_reloc_overflow;
     267        byte[0] = (u & 0xff);
     268        break;
     269      case R_MEP_16: /* fedcba9876543210 */
     270        if (u > 65535) r = bfd_reloc_overflow;
     271        byte[0^e2] = ((u >> 8) & 0xff);
     272        byte[1^e2] = (u & 0xff);
     273        break;
     274      case R_MEP_32: /* vutsrqponmlkjihgfedcba9876543210 */
     275        byte[0^e4] = ((u >> 24) & 0xff);
     276        byte[1^e4] = ((u >> 16) & 0xff);
     277        byte[2^e4] = ((u >> 8) & 0xff);
     278        byte[3^e4] = (u & 0xff);
     279        break;
     280      case R_MEP_PCREL8A2: /* --------7654321- */
     281        if (u + 128 > 255) r = bfd_reloc_overflow;
     282        byte[1^e2] = (byte[1^e2] & 0x01) | (u & 0xfe);
     283        break;
     284      case R_MEP_PCREL12A2: /* ----ba987654321- */
     285        if (u + 2048 > 4095) r = bfd_reloc_overflow;
     286        byte[0^e2] = (byte[0^e2] & 0xf0) | ((u >> 8) & 0x0f);
     287        byte[1^e2] = (byte[1^e2] & 0x01) | (u & 0xfe);
     288        break;
     289      case R_MEP_PCREL17A2: /* ----------------gfedcba987654321 */
     290        if (u + 65536 > 131071) r = bfd_reloc_overflow;
     291        byte[2^e2] = ((u >> 9) & 0xff);
     292        byte[3^e2] = ((u >> 1) & 0xff);
     293        break;
     294      case R_MEP_PCREL24A2: /* -----7654321----nmlkjihgfedcba98 */
     295        if (u + 8388608 > 16777215) r = bfd_reloc_overflow;
     296        byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
     297        byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
     298        byte[2^e2] = ((u >> 16) & 0xff);
     299        byte[3^e2] = ((u >> 8) & 0xff);
     300        break;
     301      case R_MEP_PCABS24A2: /* -----7654321----nmlkjihgfedcba98 */
     302        if (u > 16777215) r = bfd_reloc_overflow;
     303        byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
     304        byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
     305        byte[2^e2] = ((u >> 16) & 0xff);
     306        byte[3^e2] = ((u >> 8) & 0xff);
     307        break;
     308      case R_MEP_LOW16: /* ----------------fedcba9876543210 */
     309        byte[2^e2] = ((u >> 8) & 0xff);
     310        byte[3^e2] = (u & 0xff);
     311        break;
     312      case R_MEP_HI16U: /* ----------------vutsrqponmlkjihg */
     313        byte[2^e2] = ((u >> 24) & 0xff);
     314        byte[3^e2] = ((u >> 16) & 0xff);
     315        break;
     316      case R_MEP_HI16S: /* ----------------vutsrqponmlkjihg */
     317        u += 0x8000;
     318        byte[2^e2] = ((u >> 24) & 0xff);
     319        byte[3^e2] = ((u >> 16) & 0xff);
     320        break;
     321      case R_MEP_GPREL: /* ----------------fedcba9876543210 */
     322        u -= mep_sdaoff_base(rel->r_offset);
     323        if (u + 32768 > 65535) r = bfd_reloc_overflow;
     324        byte[2^e2] = ((u >> 8) & 0xff);
     325        byte[3^e2] = (u & 0xff);
     326        break;
     327      case R_MEP_TPREL: /* ----------------fedcba9876543210 */
     328        u -= mep_tpoff_base(rel->r_offset);
     329        if (u + 32768 > 65535) r = bfd_reloc_overflow;
     330        byte[2^e2] = ((u >> 8) & 0xff);
     331        byte[3^e2] = (u & 0xff);
     332        break;
     333      case R_MEP_TPREL7: /* ---------6543210 */
     334        u -= mep_tpoff_base(rel->r_offset);
     335        if (u > 127) r = bfd_reloc_overflow;
     336        byte[1^e2] = (byte[1^e2] & 0x80) | (u & 0x7f);
     337        break;
     338      case R_MEP_TPREL7A2: /* ---------654321- */
     339        u -= mep_tpoff_base(rel->r_offset);
     340        if (u > 127) r = bfd_reloc_overflow;
     341        byte[1^e2] = (byte[1^e2] & 0x81) | (u & 0x7e);
     342        break;
     343      case R_MEP_TPREL7A4: /* ---------65432-- */
     344        u -= mep_tpoff_base(rel->r_offset);
     345        if (u > 127) r = bfd_reloc_overflow;
     346        byte[1^e2] = (byte[1^e2] & 0x83) | (u & 0x7c);
     347        break;
     348      case R_MEP_UIMM24: /* --------76543210nmlkjihgfedcba98 */
     349        if (u > 16777215) r = bfd_reloc_overflow;
     350        byte[1^e2] = (u & 0xff);
     351        byte[2^e2] = ((u >> 16) & 0xff);
     352        byte[3^e2] = ((u >> 8) & 0xff);
     353        break;
     354      case R_MEP_ADDR24A4: /* --------765432--nmlkjihgfedcba98 */
     355        if (u > 16777215) r = bfd_reloc_overflow;
     356        byte[1^e2] = (byte[1^e2] & 0x03) | (u & 0xfc);
     357        byte[2^e2] = ((u >> 16) & 0xff);
     358        byte[3^e2] = ((u >> 8) & 0xff);
     359        break;
     360      case R_MEP_GNU_VTINHERIT: /* ---------------- */
     361        break;
     362      case R_MEP_GNU_VTENTRY: /* ---------------- */
     363        break;
     364      /* MEPRELOC:END */
     365      default:
     366        abort ();
     367      }
     368  
     369    return r;
     370  }
     371  
     372  /* Set the howto pointer for a MEP ELF reloc.  */
     373  
     374  static bool
     375  mep_info_to_howto_rela (bfd *		    abfd,
     376  			arelent *	    cache_ptr,
     377  			Elf_Internal_Rela * dst)
     378  {
     379    unsigned int r_type;
     380  
     381    r_type = ELF32_R_TYPE (dst->r_info);
     382    if (r_type >= R_MEP_max)
     383      {
     384        /* xgettext:c-format */
     385        _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
     386  			  abfd, r_type);
     387        bfd_set_error (bfd_error_bad_value);
     388        return false;
     389      }
     390    cache_ptr->howto = & mep_elf_howto_table [r_type];
     391    return true;
     392  }
     393  
     394  /* Relocate a MEP ELF section.
     395     There is some attempt to make this function usable for many architectures,
     396     both USE_REL and USE_RELA ['twould be nice if such a critter existed],
     397     if only to serve as a learning tool.
     398  
     399     The RELOCATE_SECTION function is called by the new ELF backend linker
     400     to handle the relocations for a section.
     401  
     402     The relocs are always passed as Rela structures; if the section
     403     actually uses Rel structures, the r_addend field will always be
     404     zero.
     405  
     406     This function is responsible for adjusting the section contents as
     407     necessary, and (if using Rela relocs and generating a relocatable
     408     output file) adjusting the reloc addend as necessary.
     409  
     410     This function does not have to worry about setting the reloc
     411     address or the reloc symbol index.
     412  
     413     LOCAL_SYMS is a pointer to the swapped in local symbols.
     414  
     415     LOCAL_SECTIONS is an array giving the section in the input file
     416     corresponding to the st_shndx field of each local symbol.
     417  
     418     The global hash table entry for the global symbols can be found
     419     via elf_sym_hashes (input_bfd).
     420  
     421     When generating relocatable output, this function must handle
     422     STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
     423     going to be the section symbol corresponding to the output
     424     section, which means that the addend must be adjusted
     425     accordingly.  */
     426  
     427  static int
     428  mep_elf_relocate_section
     429      (bfd *		     output_bfd ATTRIBUTE_UNUSED,
     430       struct bfd_link_info *  info,
     431       bfd *		     input_bfd,
     432       asection *		     input_section,
     433       bfd_byte *		     contents,
     434       Elf_Internal_Rela *     relocs,
     435       Elf_Internal_Sym *	     local_syms,
     436       asection **	     local_sections)
     437  {
     438    Elf_Internal_Shdr *		symtab_hdr;
     439    struct elf_link_hash_entry ** sym_hashes;
     440    Elf_Internal_Rela *		rel;
     441    Elf_Internal_Rela *		relend;
     442  
     443    symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
     444    sym_hashes = elf_sym_hashes (input_bfd);
     445    relend     = relocs + input_section->reloc_count;
     446  
     447    mep_info = info;
     448  
     449    for (rel = relocs; rel < relend; rel ++)
     450      {
     451        reloc_howto_type *	   howto;
     452        unsigned long		   r_symndx;
     453        Elf_Internal_Sym *	   sym;
     454        asection *		   sec;
     455        struct elf_link_hash_entry * h;
     456        bfd_vma			   relocation;
     457        bfd_reloc_status_type	   r;
     458        const char *		   name = NULL;
     459        int			   r_type;
     460  
     461        r_type = ELF32_R_TYPE (rel->r_info);
     462        r_symndx = ELF32_R_SYM (rel->r_info);
     463        howto  = mep_elf_howto_table + ELF32_R_TYPE (rel->r_info);
     464        h      = NULL;
     465        sym    = NULL;
     466        sec    = NULL;
     467  
     468        if (r_symndx < symtab_hdr->sh_info)
     469  	{
     470  	  sym = local_syms + r_symndx;
     471  	  sec = local_sections [r_symndx];
     472  	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
     473  
     474  	  name = bfd_elf_string_from_elf_section
     475  	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
     476  	  name = name == NULL ? bfd_section_name (sec) : name;
     477  	}
     478        else
     479  	{
     480  	  bool warned, unresolved_reloc, ignored;
     481  
     482  	  RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel,
     483  				  r_symndx, symtab_hdr, sym_hashes,
     484  				  h, sec, relocation,
     485  				  unresolved_reloc, warned, ignored);
     486  
     487  	  name = h->root.root.string;
     488  	}
     489  
     490        if (sec != NULL && discarded_section (sec))
     491  	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
     492  					 rel, 1, relend, howto, 0, contents);
     493  
     494        if (bfd_link_relocatable (info))
     495  	continue;
     496  
     497        if (r_type == R_RELC)
     498  	r = bfd_elf_perform_complex_relocation (input_bfd, input_section,
     499  						contents, rel, relocation);
     500        else
     501  	r = mep_final_link_relocate (howto, input_bfd, input_section,
     502  				     contents, rel, relocation);
     503  
     504        if (r != bfd_reloc_ok)
     505  	{
     506  	  const char * msg = (const char *) NULL;
     507  
     508  	  switch (r)
     509  	    {
     510  	    case bfd_reloc_overflow:
     511  	      (*info->callbacks->reloc_overflow)
     512  		(info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
     513  		 input_bfd, input_section, rel->r_offset);
     514  	      break;
     515  
     516  	    case bfd_reloc_undefined:
     517  	      (*info->callbacks->undefined_symbol)
     518  		(info, name, input_bfd, input_section, rel->r_offset, true);
     519  	      break;
     520  
     521  	    case bfd_reloc_outofrange:
     522  	      msg = _("internal error: out of range error");
     523  	      break;
     524  
     525  	    case bfd_reloc_notsupported:
     526  	      msg = _("internal error: unsupported relocation error");
     527  	      break;
     528  
     529  	    case bfd_reloc_dangerous:
     530  	      msg = _("internal error: dangerous relocation");
     531  	      break;
     532  
     533  	    default:
     534  	      msg = _("internal error: unknown error");
     535  	      break;
     536  	    }
     537  
     538  	  if (msg)
     539  	    (*info->callbacks->warning) (info, msg, name, input_bfd,
     540  					 input_section, rel->r_offset);
     541  	}
     542      }
     543  
     544    if (warn_tp)
     545      info->callbacks->undefined_symbol
     546        (info, "__tpbase", input_bfd, input_section, warn_tp-1, true);
     547    if (warn_sda)
     548      info->callbacks->undefined_symbol
     549        (info, "__sdabase", input_bfd, input_section, warn_sda-1, true);
     550    if (warn_sda || warn_tp)
     551      return false;
     552  
     553    return true;
     554  }
     555  
     556  /* Function to set the ELF flag bits.  */
     557  
     558  static bool
     559  mep_elf_set_private_flags (bfd *    abfd,
     560  			   flagword flags)
     561  {
     562    elf_elfheader (abfd)->e_flags = flags;
     563    elf_flags_init (abfd) = true;
     564    return true;
     565  }
     566  
     567  /* Merge backend specific data from an object file to the output
     568     object file when linking.  */
     569  
     570  static bool
     571  mep_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
     572  {
     573    bfd *obfd = info->output_bfd;
     574    static bfd *last_ibfd = 0;
     575    flagword old_flags, new_flags;
     576    flagword old_partial, new_partial;
     577  
     578    /* Check if we have the same endianness.  */
     579    if (!_bfd_generic_verify_endian_match (ibfd, info))
     580      return false;
     581  
     582    new_flags = elf_elfheader (ibfd)->e_flags;
     583    old_flags = elf_elfheader (obfd)->e_flags;
     584  
     585  #ifdef DEBUG
     586    _bfd_error_handler ("%pB: old_flags = 0x%.8x, new_flags = 0x%.8x, init = %s",
     587  		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
     588  #endif
     589  
     590      /* First call, no flags set.  */
     591      if (!elf_flags_init (obfd))
     592      {
     593        elf_flags_init (obfd) = true;
     594        old_flags = new_flags;
     595      }
     596    else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
     597      {
     598        /* Non-library flags trump library flags.  The choice doesn't really
     599  	 matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
     600        if (old_flags & EF_MEP_LIBRARY)
     601  	old_flags = new_flags;
     602      }
     603    else
     604      {
     605        /* Make sure they're for the same mach.  Allow upgrade from the "mep"
     606  	 mach.  */
     607        new_partial = (new_flags & EF_MEP_CPU_MASK);
     608        old_partial = (old_flags & EF_MEP_CPU_MASK);
     609        if (new_partial == old_partial)
     610  	;
     611        else if (new_partial == EF_MEP_CPU_MEP)
     612  	;
     613        else if (old_partial == EF_MEP_CPU_MEP)
     614  	old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
     615        else
     616  	{
     617  	  /* xgettext:c-format */
     618  	  _bfd_error_handler (_("%pB and %pB are for different cores"),
     619  			      last_ibfd, ibfd);
     620  	  bfd_set_error (bfd_error_invalid_target);
     621  	  return false;
     622  	}
     623  
     624        /* Make sure they're for the same me_module.  Allow basic config to
     625  	 mix with any other.  */
     626        new_partial = (new_flags & EF_MEP_INDEX_MASK);
     627        old_partial = (old_flags & EF_MEP_INDEX_MASK);
     628        if (new_partial == old_partial)
     629  	;
     630        else if (new_partial == 0)
     631  	;
     632        else if (old_partial == 0)
     633  	old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
     634        else
     635  	{
     636  	  /* xgettext:c-format */
     637  	  _bfd_error_handler (_("%pB and %pB are for different configurations"),
     638  			      last_ibfd, ibfd);
     639  	  bfd_set_error (bfd_error_invalid_target);
     640  	  return false;
     641  	}
     642      }
     643  
     644    elf_elfheader (obfd)->e_flags = old_flags;
     645    last_ibfd = ibfd;
     646    return true;
     647  }
     648  
     649  /* This will be edited by the MeP configration tool.  */
     650  static const char * config_names[] =
     651  {
     652    "basic"
     653    /* start-mepcfgtool */
     654    ,"default"
     655    /* end-mepcfgtool */
     656  };
     657  
     658  static const char * core_names[] =
     659  {
     660    "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
     661  };
     662  
     663  static bool
     664  mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
     665  {
     666    FILE *   file = (FILE *) ptr;
     667    flagword flags, partial_flags;
     668  
     669    BFD_ASSERT (abfd != NULL && ptr != NULL);
     670  
     671    /* Print normal ELF private data.  */
     672    _bfd_elf_print_private_bfd_data (abfd, ptr);
     673  
     674    flags = elf_elfheader (abfd)->e_flags;
     675    fprintf (file, _("private flags = 0x%lx"), (unsigned long) flags);
     676  
     677    partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
     678    if (partial_flags < ARRAY_SIZE (core_names))
     679      fprintf (file, "  core: %s", core_names[(long)partial_flags]);
     680  
     681    partial_flags = flags & EF_MEP_INDEX_MASK;
     682    if (partial_flags < ARRAY_SIZE (config_names))
     683      fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);
     684  
     685    fputc ('\n', file);
     686  
     687    return true;
     688  }
     689  
     690  /* Return the machine subcode from the ELF e_flags header.  */
     691  
     692  static int
     693  elf32_mep_machine (bfd * abfd)
     694  {
     695    switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
     696      {
     697      default: break;
     698      case EF_MEP_CPU_C2: return bfd_mach_mep;
     699      case EF_MEP_CPU_C3: return bfd_mach_mep;
     700      case EF_MEP_CPU_C4: return bfd_mach_mep;
     701      case EF_MEP_CPU_C5: return bfd_mach_mep_c5;
     702      case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
     703      }
     704  
     705    return bfd_mach_mep;
     706  }
     707  
     708  static bool
     709  mep_elf_object_p (bfd * abfd)
     710  {
     711    bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
     712    return true;
     713  }
     714  
     715  static bool
     716  mep_elf_section_flags (const Elf_Internal_Shdr *hdr)
     717  {
     718    if (hdr->sh_flags & SHF_MEP_VLIW)
     719      hdr->bfd_section->flags |= SEC_MEP_VLIW;
     720    return true;
     721  }
     722  
     723  static bool
     724  mep_elf_fake_sections (bfd *		   abfd ATTRIBUTE_UNUSED,
     725  		       Elf_Internal_Shdr * hdr,
     726  		       asection *	   sec)
     727  {
     728    if (sec->flags & SEC_MEP_VLIW)
     729      hdr->sh_flags |= SHF_MEP_VLIW;
     730    return true;
     731  }
     732  
     733  
     734  #define ELF_ARCH		bfd_arch_mep
     735  #define ELF_MACHINE_CODE	EM_CYGNUS_MEP
     736  #define ELF_MAXPAGESIZE		0x1000
     737  
     738  #define TARGET_BIG_SYM		mep_elf32_vec
     739  #define TARGET_BIG_NAME		"elf32-mep"
     740  
     741  #define TARGET_LITTLE_SYM	mep_elf32_le_vec
     742  #define TARGET_LITTLE_NAME	"elf32-mep-little"
     743  
     744  #define elf_info_to_howto_rel			NULL
     745  #define elf_info_to_howto			mep_info_to_howto_rela
     746  #define elf_backend_relocate_section		mep_elf_relocate_section
     747  #define elf_backend_object_p			mep_elf_object_p
     748  #define elf_backend_section_flags		mep_elf_section_flags
     749  #define elf_backend_fake_sections		mep_elf_fake_sections
     750  
     751  #define bfd_elf32_bfd_reloc_type_lookup		mep_reloc_type_lookup
     752  #define bfd_elf32_bfd_reloc_name_lookup		mep_reloc_name_lookup
     753  #define bfd_elf32_bfd_set_private_flags		mep_elf_set_private_flags
     754  #define bfd_elf32_bfd_merge_private_bfd_data	mep_elf_merge_private_bfd_data
     755  #define bfd_elf32_bfd_print_private_bfd_data	mep_elf_print_private_bfd_data
     756  
     757  #define elf_backend_rela_normal			1
     758  
     759  #include "elf32-target.h"