xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/elf32-mep.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /* MeP-specific support for 32-bit ELF.
2    Copyright (C) 2001-2016 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   {(unsigned)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,     3,  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,        0,  8, 0, 0, 0, U, 0xff),
47   MEPREL (R_MEP_16,       1, 16, 0, 0, 0, U, 0xffff),
48   MEPREL (R_MEP_32,       2, 32, 0, 0, 0, U, 0xffffffff),
49   MEPREL (R_MEP_PCREL8A2, 1,  8, 1, 1, 1, S, 0x00fe),
50   MEPREL (R_MEP_PCREL12A2,1, 12, 1, 1, 1, S, 0x0ffe),
51   MEPREL (R_MEP_PCREL17A2,2, 17, 0, 1, 1, S, 0x0000ffff),
52   MEPREL (R_MEP_PCREL24A2,2, 24, 0, 1, 1, S, 0x07f0ffff),
53   MEPREL (R_MEP_PCABS24A2,2, 24, 0, 1, 0, U, 0x07f0ffff),
54   MEPREL (R_MEP_LOW16,    2, 16, 0, 0, 0, N, 0x0000ffff),
55   MEPREL (R_MEP_HI16U,    2, 32, 0,16, 0, N, 0x0000ffff),
56   MEPREL (R_MEP_HI16S,    2, 32, 0,16, 0, N, 0x0000ffff),
57   MEPREL (R_MEP_GPREL,    2, 16, 0, 0, 0, S, 0x0000ffff),
58   MEPREL (R_MEP_TPREL,    2, 16, 0, 0, 0, S, 0x0000ffff),
59   MEPREL (R_MEP_TPREL7,   1,  7, 0, 0, 0, U, 0x007f),
60   MEPREL (R_MEP_TPREL7A2, 1,  7, 1, 1, 0, U, 0x007e),
61   MEPREL (R_MEP_TPREL7A4, 1,  7, 2, 2, 0, U, 0x007c),
62   MEPREL (R_MEP_UIMM24,   2, 24, 0, 0, 0, U, 0x00ffffff),
63   MEPREL (R_MEP_ADDR24A4, 2, 24, 0, 2, 0, U, 0x00fcffff),
64   MEPREL (R_MEP_GNU_VTINHERIT,1,  0,16,32, 0, N, 0x0000),
65   MEPREL (R_MEP_GNU_VTENTRY,1,  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       (*_bfd_error_handler) (_("MeP: howto %d has type %d"),
146 			     type, mep_elf_howto_table[type].type);
147       abort ();
148     }
149 
150   return mep_elf_howto_table + type;
151 }
152 
153 #undef MAP
154 
155 static reloc_howto_type *
156 mep_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
157 {
158   unsigned int i;
159 
160   for (i = 0;
161        i < sizeof (mep_elf_howto_table) / sizeof (mep_elf_howto_table[0]);
162        i++)
163     if (mep_elf_howto_table[i].name != NULL
164 	&& strcasecmp (mep_elf_howto_table[i].name, r_name) == 0)
165       return &mep_elf_howto_table[i];
166 
167   return NULL;
168 }
169 
170 /* Perform a single relocation.  */
171 
172 static struct bfd_link_info *mep_info;
173 static int warn_tp = 0, warn_sda = 0;
174 
175 static bfd_vma
176 mep_lookup_global
177     (char *    name,
178      bfd_vma   ofs,
179      bfd_vma * cache,
180      int *     warn)
181 {
182   struct bfd_link_hash_entry *h;
183 
184   if (*cache || *warn)
185     return *cache;
186 
187   h = bfd_link_hash_lookup (mep_info->hash, name, FALSE, FALSE, TRUE);
188   if (h == 0 || h->type != bfd_link_hash_defined)
189     {
190       *warn = ofs + 1;
191       return 0;
192     }
193   *cache = (h->u.def.value
194 	  + h->u.def.section->output_section->vma
195 	  + h->u.def.section->output_offset);
196   return *cache;
197 }
198 
199 static bfd_vma
200 mep_tpoff_base (bfd_vma ofs)
201 {
202   static bfd_vma cache = 0;
203   return mep_lookup_global ("__tpbase", ofs, &cache, &warn_tp);
204 }
205 
206 static bfd_vma
207 mep_sdaoff_base (bfd_vma ofs)
208 {
209   static bfd_vma cache = 0;
210   return mep_lookup_global ("__sdabase", ofs, &cache, &warn_sda);
211 }
212 
213 static bfd_reloc_status_type
214 mep_final_link_relocate
215     (reloc_howto_type *  howto,
216      bfd *               input_bfd,
217      asection *          input_section,
218      bfd_byte *          contents,
219      Elf_Internal_Rela * rel,
220      bfd_vma             relocation)
221 {
222   unsigned long u;
223   long s;
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   s = relocation + rel->r_addend;
245 
246   byte = (unsigned char *)contents + rel->r_offset;
247 
248   if (howto->type == R_MEP_PCREL24A2
249       && s == 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     s -= pc;
260 
261   u = (unsigned long) s;
262 
263   switch (howto->type)
264     {
265     /* MEPRELOC:APPLY */
266     /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
267     case R_MEP_8: /* 76543210 */
268       if (u > 255) r = bfd_reloc_overflow;
269       byte[0] = (u & 0xff);
270       break;
271     case R_MEP_16: /* fedcba9876543210 */
272       if (u > 65535) r = bfd_reloc_overflow;
273       byte[0^e2] = ((u >> 8) & 0xff);
274       byte[1^e2] = (u & 0xff);
275       break;
276     case R_MEP_32: /* vutsrqponmlkjihgfedcba9876543210 */
277       byte[0^e4] = ((u >> 24) & 0xff);
278       byte[1^e4] = ((u >> 16) & 0xff);
279       byte[2^e4] = ((u >> 8) & 0xff);
280       byte[3^e4] = (u & 0xff);
281       break;
282     case R_MEP_PCREL8A2: /* --------7654321- */
283       if (-128 > s || s > 127) r = bfd_reloc_overflow;
284       byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
285       break;
286     case R_MEP_PCREL12A2: /* ----ba987654321- */
287       if (-2048 > s || s > 2047) r = bfd_reloc_overflow;
288       byte[0^e2] = (byte[0^e2] & 0xf0) | ((s >> 8) & 0x0f);
289       byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
290       break;
291     case R_MEP_PCREL17A2: /* ----------------gfedcba987654321 */
292       if (-65536 > s || s > 65535) r = bfd_reloc_overflow;
293       byte[2^e2] = ((s >> 9) & 0xff);
294       byte[3^e2] = ((s >> 1) & 0xff);
295       break;
296     case R_MEP_PCREL24A2: /* -----7654321----nmlkjihgfedcba98 */
297       if (-8388608 > s || s > 8388607) r = bfd_reloc_overflow;
298       byte[0^e2] = (byte[0^e2] & 0xf8) | ((s >> 5) & 0x07);
299       byte[1^e2] = (byte[1^e2] & 0x0f) | ((s << 3) & 0xf0);
300       byte[2^e2] = ((s >> 16) & 0xff);
301       byte[3^e2] = ((s >> 8) & 0xff);
302       break;
303     case R_MEP_PCABS24A2: /* -----7654321----nmlkjihgfedcba98 */
304       if (u > 16777215) r = bfd_reloc_overflow;
305       byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
306       byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
307       byte[2^e2] = ((u >> 16) & 0xff);
308       byte[3^e2] = ((u >> 8) & 0xff);
309       break;
310     case R_MEP_LOW16: /* ----------------fedcba9876543210 */
311       byte[2^e2] = ((u >> 8) & 0xff);
312       byte[3^e2] = (u & 0xff);
313       break;
314     case R_MEP_HI16U: /* ----------------vutsrqponmlkjihg */
315       byte[2^e2] = ((u >> 24) & 0xff);
316       byte[3^e2] = ((u >> 16) & 0xff);
317       break;
318     case R_MEP_HI16S: /* ----------------vutsrqponmlkjihg */
319       if (s & 0x8000)
320 	s += 0x10000;
321       byte[2^e2] = ((s >> 24) & 0xff);
322       byte[3^e2] = ((s >> 16) & 0xff);
323       break;
324     case R_MEP_GPREL: /* ----------------fedcba9876543210 */
325       s -= mep_sdaoff_base(rel->r_offset);
326       if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
327       byte[2^e2] = ((s >> 8) & 0xff);
328       byte[3^e2] = (s & 0xff);
329       break;
330     case R_MEP_TPREL: /* ----------------fedcba9876543210 */
331       s -= mep_tpoff_base(rel->r_offset);
332       if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
333       byte[2^e2] = ((s >> 8) & 0xff);
334       byte[3^e2] = (s & 0xff);
335       break;
336     case R_MEP_TPREL7: /* ---------6543210 */
337       u -= mep_tpoff_base(rel->r_offset);
338       if (u > 127) r = bfd_reloc_overflow;
339       byte[1^e2] = (byte[1^e2] & 0x80) | (u & 0x7f);
340       break;
341     case R_MEP_TPREL7A2: /* ---------654321- */
342       u -= mep_tpoff_base(rel->r_offset);
343       if (u > 127) r = bfd_reloc_overflow;
344       byte[1^e2] = (byte[1^e2] & 0x81) | (u & 0x7e);
345       break;
346     case R_MEP_TPREL7A4: /* ---------65432-- */
347       u -= mep_tpoff_base(rel->r_offset);
348       if (u > 127) r = bfd_reloc_overflow;
349       byte[1^e2] = (byte[1^e2] & 0x83) | (u & 0x7c);
350       break;
351     case R_MEP_UIMM24: /* --------76543210nmlkjihgfedcba98 */
352       if (u > 16777215) r = bfd_reloc_overflow;
353       byte[1^e2] = (u & 0xff);
354       byte[2^e2] = ((u >> 16) & 0xff);
355       byte[3^e2] = ((u >> 8) & 0xff);
356       break;
357     case R_MEP_ADDR24A4: /* --------765432--nmlkjihgfedcba98 */
358       if (u > 16777215) r = bfd_reloc_overflow;
359       byte[1^e2] = (byte[1^e2] & 0x03) | (u & 0xfc);
360       byte[2^e2] = ((u >> 16) & 0xff);
361       byte[3^e2] = ((u >> 8) & 0xff);
362       break;
363     case R_MEP_GNU_VTINHERIT: /* ---------------- */
364       break;
365     case R_MEP_GNU_VTENTRY: /* ---------------- */
366       break;
367     /* MEPRELOC:END */
368     default:
369       abort ();
370     }
371 
372   return r;
373 }
374 
375 /* Set the howto pointer for a MEP ELF reloc.  */
376 
377 static void
378 mep_info_to_howto_rela
379     (bfd *               abfd ATTRIBUTE_UNUSED,
380      arelent *           cache_ptr,
381      Elf_Internal_Rela * dst)
382 {
383   unsigned int r_type;
384 
385   r_type = ELF32_R_TYPE (dst->r_info);
386   if (r_type >= R_MEP_max)
387     {
388       _bfd_error_handler (_("%B: invalid MEP reloc number: %d"), abfd, r_type);
389       r_type = 0;
390     }
391   cache_ptr->howto = & mep_elf_howto_table [r_type];
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 bfd_boolean
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 (input_bfd, sec) : name;
477 	}
478       else
479 	{
480 	  bfd_boolean 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 bfd_boolean
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 bfd_boolean
571 mep_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
572 {
573   static bfd *last_ibfd = 0;
574   flagword old_flags, new_flags;
575   flagword old_partial, new_partial;
576 
577   /* Check if we have the same endianness.  */
578   if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
579     return FALSE;
580 
581   new_flags = elf_elfheader (ibfd)->e_flags;
582   old_flags = elf_elfheader (obfd)->e_flags;
583 
584 #ifdef DEBUG
585   _bfd_error_handler ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s",
586 		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
587 #endif
588 
589     /* First call, no flags set.  */
590     if (!elf_flags_init (obfd))
591     {
592       elf_flags_init (obfd) = TRUE;
593       old_flags = new_flags;
594     }
595   else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
596     {
597       /* Non-library flags trump library flags.  The choice doesn't really
598 	 matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
599       if (old_flags & EF_MEP_LIBRARY)
600 	old_flags = new_flags;
601     }
602   else
603     {
604       /* Make sure they're for the same mach.  Allow upgrade from the "mep"
605 	 mach.  */
606       new_partial = (new_flags & EF_MEP_CPU_MASK);
607       old_partial = (old_flags & EF_MEP_CPU_MASK);
608       if (new_partial == old_partial)
609 	;
610       else if (new_partial == EF_MEP_CPU_MEP)
611 	;
612       else if (old_partial == EF_MEP_CPU_MEP)
613 	old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
614       else
615 	{
616 	  _bfd_error_handler (_("%B and %B are for different cores"), last_ibfd, ibfd);
617 	  bfd_set_error (bfd_error_invalid_target);
618 	  return FALSE;
619 	}
620 
621       /* Make sure they're for the same me_module.  Allow basic config to
622 	 mix with any other.  */
623       new_partial = (new_flags & EF_MEP_INDEX_MASK);
624       old_partial = (old_flags & EF_MEP_INDEX_MASK);
625       if (new_partial == old_partial)
626 	;
627       else if (new_partial == 0)
628 	;
629       else if (old_partial == 0)
630 	old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
631       else
632 	{
633 	  _bfd_error_handler (_("%B and %B are for different configurations"), last_ibfd, ibfd);
634 	  bfd_set_error (bfd_error_invalid_target);
635 	  return FALSE;
636 	}
637     }
638 
639   elf_elfheader (obfd)->e_flags = old_flags;
640   last_ibfd = ibfd;
641   return TRUE;
642 }
643 
644 /* This will be edited by the MeP configration tool.  */
645 static const char * config_names[] =
646 {
647   "basic"
648   /* start-mepcfgtool */
649   ,"default"
650   /* end-mepcfgtool */
651 };
652 
653 static const char * core_names[] =
654 {
655   "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
656 };
657 
658 static bfd_boolean
659 mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
660 {
661   FILE *   file = (FILE *) ptr;
662   flagword flags, partial_flags;
663 
664   BFD_ASSERT (abfd != NULL && ptr != NULL);
665 
666   /* Print normal ELF private data.  */
667   _bfd_elf_print_private_bfd_data (abfd, ptr);
668 
669   flags = elf_elfheader (abfd)->e_flags;
670   fprintf (file, _("private flags = 0x%lx"), (unsigned long) flags);
671 
672   partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
673   if (partial_flags < ARRAY_SIZE (core_names))
674     fprintf (file, "  core: %s", core_names[(long)partial_flags]);
675 
676   partial_flags = flags & EF_MEP_INDEX_MASK;
677   if (partial_flags < ARRAY_SIZE (config_names))
678     fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);
679 
680   fputc ('\n', file);
681 
682   return TRUE;
683 }
684 
685 /* Return the machine subcode from the ELF e_flags header.  */
686 
687 static int
688 elf32_mep_machine (bfd * abfd)
689 {
690   switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
691     {
692     default: break;
693     case EF_MEP_CPU_C2: return bfd_mach_mep;
694     case EF_MEP_CPU_C3: return bfd_mach_mep;
695     case EF_MEP_CPU_C4: return bfd_mach_mep;
696     case EF_MEP_CPU_C5: return bfd_mach_mep_c5;
697     case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
698     }
699 
700   return bfd_mach_mep;
701 }
702 
703 static bfd_boolean
704 mep_elf_object_p (bfd * abfd)
705 {
706   bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
707   return TRUE;
708 }
709 
710 static bfd_boolean
711 mep_elf_section_flags (flagword * flags, const Elf_Internal_Shdr * hdr)
712 {
713   if (hdr->sh_flags & SHF_MEP_VLIW)
714     * flags |= SEC_MEP_VLIW;
715   return TRUE;
716 }
717 
718 static bfd_boolean
719 mep_elf_fake_sections (bfd *               abfd ATTRIBUTE_UNUSED,
720 		       Elf_Internal_Shdr * hdr,
721 		       asection *          sec)
722 {
723   if (sec->flags & SEC_MEP_VLIW)
724     hdr->sh_flags |= SHF_MEP_VLIW;
725   return TRUE;
726 }
727 
728 
729 #define ELF_ARCH		bfd_arch_mep
730 #define ELF_MACHINE_CODE	EM_CYGNUS_MEP
731 #define ELF_MAXPAGESIZE		0x1000
732 
733 #define TARGET_BIG_SYM		mep_elf32_vec
734 #define TARGET_BIG_NAME		"elf32-mep"
735 
736 #define TARGET_LITTLE_SYM	mep_elf32_le_vec
737 #define TARGET_LITTLE_NAME	"elf32-mep-little"
738 
739 #define elf_info_to_howto_rel			NULL
740 #define elf_info_to_howto			mep_info_to_howto_rela
741 #define elf_backend_relocate_section		mep_elf_relocate_section
742 #define elf_backend_object_p		        mep_elf_object_p
743 #define elf_backend_section_flags		mep_elf_section_flags
744 #define elf_backend_fake_sections		mep_elf_fake_sections
745 
746 #define bfd_elf32_bfd_reloc_type_lookup		mep_reloc_type_lookup
747 #define bfd_elf32_bfd_reloc_name_lookup		mep_reloc_name_lookup
748 #define bfd_elf32_bfd_set_private_flags		mep_elf_set_private_flags
749 #define bfd_elf32_bfd_merge_private_bfd_data	mep_elf_merge_private_bfd_data
750 #define bfd_elf32_bfd_print_private_bfd_data	mep_elf_print_private_bfd_data
751 
752 #define elf_backend_rela_normal			1
753 
754 #include "elf32-target.h"
755