xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/elf32-mep.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1 /* MeP-specific support for 32-bit ELF.
2    Copyright (C) 2001-2020 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,	  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       /* 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   long s;
225   unsigned char *byte;
226   bfd_vma pc;
227   bfd_reloc_status_type r = bfd_reloc_ok;
228   int e2, e4;
229 
230   if (bfd_big_endian (input_bfd))
231     {
232       e2 = 0;
233       e4 = 0;
234     }
235   else
236     {
237       e2 = 1;
238       e4 = 3;
239     }
240 
241   pc = (input_section->output_section->vma
242 	+ input_section->output_offset
243 	+ rel->r_offset);
244 
245   s = relocation + rel->r_addend;
246 
247   byte = (unsigned char *)contents + rel->r_offset;
248 
249   if (howto->type == R_MEP_PCREL24A2
250       && s == 0
251       && pc >= 0x800000)
252     {
253       /* This is an unreachable branch to an undefined weak function.
254 	 Silently ignore it, since the opcode can't do that but should
255 	 never be executed anyway.  */
256       return bfd_reloc_ok;
257     }
258 
259   if (howto->pc_relative)
260     s -= pc;
261 
262   u = (unsigned long) s;
263 
264   switch (howto->type)
265     {
266     /* MEPRELOC:APPLY */
267     /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
268     case R_MEP_8: /* 76543210 */
269       if (u > 255) r = bfd_reloc_overflow;
270       byte[0] = (u & 0xff);
271       break;
272     case R_MEP_16: /* fedcba9876543210 */
273       if (u > 65535) r = bfd_reloc_overflow;
274       byte[0^e2] = ((u >> 8) & 0xff);
275       byte[1^e2] = (u & 0xff);
276       break;
277     case R_MEP_32: /* vutsrqponmlkjihgfedcba9876543210 */
278       byte[0^e4] = ((u >> 24) & 0xff);
279       byte[1^e4] = ((u >> 16) & 0xff);
280       byte[2^e4] = ((u >> 8) & 0xff);
281       byte[3^e4] = (u & 0xff);
282       break;
283     case R_MEP_PCREL8A2: /* --------7654321- */
284       if (-128 > s || s > 127) r = bfd_reloc_overflow;
285       byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
286       break;
287     case R_MEP_PCREL12A2: /* ----ba987654321- */
288       if (-2048 > s || s > 2047) r = bfd_reloc_overflow;
289       byte[0^e2] = (byte[0^e2] & 0xf0) | ((s >> 8) & 0x0f);
290       byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
291       break;
292     case R_MEP_PCREL17A2: /* ----------------gfedcba987654321 */
293       if (-65536 > s || s > 65535) r = bfd_reloc_overflow;
294       byte[2^e2] = ((s >> 9) & 0xff);
295       byte[3^e2] = ((s >> 1) & 0xff);
296       break;
297     case R_MEP_PCREL24A2: /* -----7654321----nmlkjihgfedcba98 */
298       if (-8388608 > s || s > 8388607) r = bfd_reloc_overflow;
299       byte[0^e2] = (byte[0^e2] & 0xf8) | ((s >> 5) & 0x07);
300       byte[1^e2] = (byte[1^e2] & 0x0f) | ((s << 3) & 0xf0);
301       byte[2^e2] = ((s >> 16) & 0xff);
302       byte[3^e2] = ((s >> 8) & 0xff);
303       break;
304     case R_MEP_PCABS24A2: /* -----7654321----nmlkjihgfedcba98 */
305       if (u > 16777215) r = bfd_reloc_overflow;
306       byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
307       byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
308       byte[2^e2] = ((u >> 16) & 0xff);
309       byte[3^e2] = ((u >> 8) & 0xff);
310       break;
311     case R_MEP_LOW16: /* ----------------fedcba9876543210 */
312       byte[2^e2] = ((u >> 8) & 0xff);
313       byte[3^e2] = (u & 0xff);
314       break;
315     case R_MEP_HI16U: /* ----------------vutsrqponmlkjihg */
316       byte[2^e2] = ((u >> 24) & 0xff);
317       byte[3^e2] = ((u >> 16) & 0xff);
318       break;
319     case R_MEP_HI16S: /* ----------------vutsrqponmlkjihg */
320       if (s & 0x8000)
321 	s += 0x10000;
322       byte[2^e2] = ((s >> 24) & 0xff);
323       byte[3^e2] = ((s >> 16) & 0xff);
324       break;
325     case R_MEP_GPREL: /* ----------------fedcba9876543210 */
326       s -= mep_sdaoff_base(rel->r_offset);
327       if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
328       byte[2^e2] = ((s >> 8) & 0xff);
329       byte[3^e2] = (s & 0xff);
330       break;
331     case R_MEP_TPREL: /* ----------------fedcba9876543210 */
332       s -= mep_tpoff_base(rel->r_offset);
333       if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
334       byte[2^e2] = ((s >> 8) & 0xff);
335       byte[3^e2] = (s & 0xff);
336       break;
337     case R_MEP_TPREL7: /* ---------6543210 */
338       u -= mep_tpoff_base(rel->r_offset);
339       if (u > 127) r = bfd_reloc_overflow;
340       byte[1^e2] = (byte[1^e2] & 0x80) | (u & 0x7f);
341       break;
342     case R_MEP_TPREL7A2: /* ---------654321- */
343       u -= mep_tpoff_base(rel->r_offset);
344       if (u > 127) r = bfd_reloc_overflow;
345       byte[1^e2] = (byte[1^e2] & 0x81) | (u & 0x7e);
346       break;
347     case R_MEP_TPREL7A4: /* ---------65432-- */
348       u -= mep_tpoff_base(rel->r_offset);
349       if (u > 127) r = bfd_reloc_overflow;
350       byte[1^e2] = (byte[1^e2] & 0x83) | (u & 0x7c);
351       break;
352     case R_MEP_UIMM24: /* --------76543210nmlkjihgfedcba98 */
353       if (u > 16777215) r = bfd_reloc_overflow;
354       byte[1^e2] = (u & 0xff);
355       byte[2^e2] = ((u >> 16) & 0xff);
356       byte[3^e2] = ((u >> 8) & 0xff);
357       break;
358     case R_MEP_ADDR24A4: /* --------765432--nmlkjihgfedcba98 */
359       if (u > 16777215) r = bfd_reloc_overflow;
360       byte[1^e2] = (byte[1^e2] & 0x03) | (u & 0xfc);
361       byte[2^e2] = ((u >> 16) & 0xff);
362       byte[3^e2] = ((u >> 8) & 0xff);
363       break;
364     case R_MEP_GNU_VTINHERIT: /* ---------------- */
365       break;
366     case R_MEP_GNU_VTENTRY: /* ---------------- */
367       break;
368     /* MEPRELOC:END */
369     default:
370       abort ();
371     }
372 
373   return r;
374 }
375 
376 /* Set the howto pointer for a MEP ELF reloc.  */
377 
378 static bfd_boolean
379 mep_info_to_howto_rela (bfd *		    abfd,
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       /* xgettext:c-format */
389       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
390 			  abfd, r_type);
391       bfd_set_error (bfd_error_bad_value);
392       return FALSE;
393     }
394   cache_ptr->howto = & mep_elf_howto_table [r_type];
395   return TRUE;
396 }
397 
398 /* Relocate a MEP ELF section.
399    There is some attempt to make this function usable for many architectures,
400    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
401    if only to serve as a learning tool.
402 
403    The RELOCATE_SECTION function is called by the new ELF backend linker
404    to handle the relocations for a section.
405 
406    The relocs are always passed as Rela structures; if the section
407    actually uses Rel structures, the r_addend field will always be
408    zero.
409 
410    This function is responsible for adjusting the section contents as
411    necessary, and (if using Rela relocs and generating a relocatable
412    output file) adjusting the reloc addend as necessary.
413 
414    This function does not have to worry about setting the reloc
415    address or the reloc symbol index.
416 
417    LOCAL_SYMS is a pointer to the swapped in local symbols.
418 
419    LOCAL_SECTIONS is an array giving the section in the input file
420    corresponding to the st_shndx field of each local symbol.
421 
422    The global hash table entry for the global symbols can be found
423    via elf_sym_hashes (input_bfd).
424 
425    When generating relocatable output, this function must handle
426    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
427    going to be the section symbol corresponding to the output
428    section, which means that the addend must be adjusted
429    accordingly.  */
430 
431 static bfd_boolean
432 mep_elf_relocate_section
433     (bfd *		     output_bfd ATTRIBUTE_UNUSED,
434      struct bfd_link_info *  info,
435      bfd *		     input_bfd,
436      asection *		     input_section,
437      bfd_byte *		     contents,
438      Elf_Internal_Rela *     relocs,
439      Elf_Internal_Sym *	     local_syms,
440      asection **	     local_sections)
441 {
442   Elf_Internal_Shdr *		symtab_hdr;
443   struct elf_link_hash_entry ** sym_hashes;
444   Elf_Internal_Rela *		rel;
445   Elf_Internal_Rela *		relend;
446 
447   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
448   sym_hashes = elf_sym_hashes (input_bfd);
449   relend     = relocs + input_section->reloc_count;
450 
451   mep_info = info;
452 
453   for (rel = relocs; rel < relend; rel ++)
454     {
455       reloc_howto_type *	   howto;
456       unsigned long		   r_symndx;
457       Elf_Internal_Sym *	   sym;
458       asection *		   sec;
459       struct elf_link_hash_entry * h;
460       bfd_vma			   relocation;
461       bfd_reloc_status_type	   r;
462       const char *		   name = NULL;
463       int			   r_type;
464 
465       r_type = ELF32_R_TYPE (rel->r_info);
466       r_symndx = ELF32_R_SYM (rel->r_info);
467       howto  = mep_elf_howto_table + ELF32_R_TYPE (rel->r_info);
468       h      = NULL;
469       sym    = NULL;
470       sec    = NULL;
471 
472       if (r_symndx < symtab_hdr->sh_info)
473 	{
474 	  sym = local_syms + r_symndx;
475 	  sec = local_sections [r_symndx];
476 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
477 
478 	  name = bfd_elf_string_from_elf_section
479 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
480 	  name = name == NULL ? bfd_section_name (sec) : name;
481 	}
482       else
483 	{
484 	  bfd_boolean warned, unresolved_reloc, ignored;
485 
486 	  RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel,
487 				  r_symndx, symtab_hdr, sym_hashes,
488 				  h, sec, relocation,
489 				  unresolved_reloc, warned, ignored);
490 
491 	  name = h->root.root.string;
492 	}
493 
494       if (sec != NULL && discarded_section (sec))
495 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
496 					 rel, 1, relend, howto, 0, contents);
497 
498       if (bfd_link_relocatable (info))
499 	continue;
500 
501       if (r_type == R_RELC)
502 	r = bfd_elf_perform_complex_relocation (input_bfd, input_section,
503 						contents, rel, relocation);
504       else
505 	r = mep_final_link_relocate (howto, input_bfd, input_section,
506 				     contents, rel, relocation);
507 
508       if (r != bfd_reloc_ok)
509 	{
510 	  const char * msg = (const char *) NULL;
511 
512 	  switch (r)
513 	    {
514 	    case bfd_reloc_overflow:
515 	      (*info->callbacks->reloc_overflow)
516 		(info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
517 		 input_bfd, input_section, rel->r_offset);
518 	      break;
519 
520 	    case bfd_reloc_undefined:
521 	      (*info->callbacks->undefined_symbol)
522 		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
523 	      break;
524 
525 	    case bfd_reloc_outofrange:
526 	      msg = _("internal error: out of range error");
527 	      break;
528 
529 	    case bfd_reloc_notsupported:
530 	      msg = _("internal error: unsupported relocation error");
531 	      break;
532 
533 	    case bfd_reloc_dangerous:
534 	      msg = _("internal error: dangerous relocation");
535 	      break;
536 
537 	    default:
538 	      msg = _("internal error: unknown error");
539 	      break;
540 	    }
541 
542 	  if (msg)
543 	    (*info->callbacks->warning) (info, msg, name, input_bfd,
544 					 input_section, rel->r_offset);
545 	}
546     }
547 
548   if (warn_tp)
549     info->callbacks->undefined_symbol
550       (info, "__tpbase", input_bfd, input_section, warn_tp-1, TRUE);
551   if (warn_sda)
552     info->callbacks->undefined_symbol
553       (info, "__sdabase", input_bfd, input_section, warn_sda-1, TRUE);
554   if (warn_sda || warn_tp)
555     return FALSE;
556 
557   return TRUE;
558 }
559 
560 /* Function to set the ELF flag bits.  */
561 
562 static bfd_boolean
563 mep_elf_set_private_flags (bfd *    abfd,
564 			   flagword flags)
565 {
566   elf_elfheader (abfd)->e_flags = flags;
567   elf_flags_init (abfd) = TRUE;
568   return TRUE;
569 }
570 
571 /* Merge backend specific data from an object file to the output
572    object file when linking.  */
573 
574 static bfd_boolean
575 mep_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
576 {
577   bfd *obfd = info->output_bfd;
578   static bfd *last_ibfd = 0;
579   flagword old_flags, new_flags;
580   flagword old_partial, new_partial;
581 
582   /* Check if we have the same endianness.  */
583   if (!_bfd_generic_verify_endian_match (ibfd, info))
584     return FALSE;
585 
586   new_flags = elf_elfheader (ibfd)->e_flags;
587   old_flags = elf_elfheader (obfd)->e_flags;
588 
589 #ifdef DEBUG
590   _bfd_error_handler ("%pB: old_flags = 0x%.8x, new_flags = 0x%.8x, init = %s",
591 		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
592 #endif
593 
594     /* First call, no flags set.  */
595     if (!elf_flags_init (obfd))
596     {
597       elf_flags_init (obfd) = TRUE;
598       old_flags = new_flags;
599     }
600   else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
601     {
602       /* Non-library flags trump library flags.  The choice doesn't really
603 	 matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
604       if (old_flags & EF_MEP_LIBRARY)
605 	old_flags = new_flags;
606     }
607   else
608     {
609       /* Make sure they're for the same mach.  Allow upgrade from the "mep"
610 	 mach.  */
611       new_partial = (new_flags & EF_MEP_CPU_MASK);
612       old_partial = (old_flags & EF_MEP_CPU_MASK);
613       if (new_partial == old_partial)
614 	;
615       else if (new_partial == EF_MEP_CPU_MEP)
616 	;
617       else if (old_partial == EF_MEP_CPU_MEP)
618 	old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
619       else
620 	{
621 	  /* xgettext:c-format */
622 	  _bfd_error_handler (_("%pB and %pB are for different cores"),
623 			      last_ibfd, ibfd);
624 	  bfd_set_error (bfd_error_invalid_target);
625 	  return FALSE;
626 	}
627 
628       /* Make sure they're for the same me_module.  Allow basic config to
629 	 mix with any other.  */
630       new_partial = (new_flags & EF_MEP_INDEX_MASK);
631       old_partial = (old_flags & EF_MEP_INDEX_MASK);
632       if (new_partial == old_partial)
633 	;
634       else if (new_partial == 0)
635 	;
636       else if (old_partial == 0)
637 	old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
638       else
639 	{
640 	  /* xgettext:c-format */
641 	  _bfd_error_handler (_("%pB and %pB are for different configurations"),
642 			      last_ibfd, ibfd);
643 	  bfd_set_error (bfd_error_invalid_target);
644 	  return FALSE;
645 	}
646     }
647 
648   elf_elfheader (obfd)->e_flags = old_flags;
649   last_ibfd = ibfd;
650   return TRUE;
651 }
652 
653 /* This will be edited by the MeP configration tool.  */
654 static const char * config_names[] =
655 {
656   "basic"
657   /* start-mepcfgtool */
658   ,"default"
659   /* end-mepcfgtool */
660 };
661 
662 static const char * core_names[] =
663 {
664   "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
665 };
666 
667 static bfd_boolean
668 mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
669 {
670   FILE *   file = (FILE *) ptr;
671   flagword flags, partial_flags;
672 
673   BFD_ASSERT (abfd != NULL && ptr != NULL);
674 
675   /* Print normal ELF private data.  */
676   _bfd_elf_print_private_bfd_data (abfd, ptr);
677 
678   flags = elf_elfheader (abfd)->e_flags;
679   fprintf (file, _("private flags = 0x%lx"), (unsigned long) flags);
680 
681   partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
682   if (partial_flags < ARRAY_SIZE (core_names))
683     fprintf (file, "  core: %s", core_names[(long)partial_flags]);
684 
685   partial_flags = flags & EF_MEP_INDEX_MASK;
686   if (partial_flags < ARRAY_SIZE (config_names))
687     fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);
688 
689   fputc ('\n', file);
690 
691   return TRUE;
692 }
693 
694 /* Return the machine subcode from the ELF e_flags header.  */
695 
696 static int
697 elf32_mep_machine (bfd * abfd)
698 {
699   switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
700     {
701     default: break;
702     case EF_MEP_CPU_C2: return bfd_mach_mep;
703     case EF_MEP_CPU_C3: return bfd_mach_mep;
704     case EF_MEP_CPU_C4: return bfd_mach_mep;
705     case EF_MEP_CPU_C5: return bfd_mach_mep_c5;
706     case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
707     }
708 
709   return bfd_mach_mep;
710 }
711 
712 static bfd_boolean
713 mep_elf_object_p (bfd * abfd)
714 {
715   bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
716   return TRUE;
717 }
718 
719 static bfd_boolean
720 mep_elf_section_flags (flagword * flags, const Elf_Internal_Shdr * hdr)
721 {
722   if (hdr->sh_flags & SHF_MEP_VLIW)
723     * flags |= SEC_MEP_VLIW;
724   return TRUE;
725 }
726 
727 static bfd_boolean
728 mep_elf_fake_sections (bfd *		   abfd ATTRIBUTE_UNUSED,
729 		       Elf_Internal_Shdr * hdr,
730 		       asection *	   sec)
731 {
732   if (sec->flags & SEC_MEP_VLIW)
733     hdr->sh_flags |= SHF_MEP_VLIW;
734   return TRUE;
735 }
736 
737 
738 #define ELF_ARCH		bfd_arch_mep
739 #define ELF_MACHINE_CODE	EM_CYGNUS_MEP
740 #define ELF_MAXPAGESIZE		0x1000
741 
742 #define TARGET_BIG_SYM		mep_elf32_vec
743 #define TARGET_BIG_NAME		"elf32-mep"
744 
745 #define TARGET_LITTLE_SYM	mep_elf32_le_vec
746 #define TARGET_LITTLE_NAME	"elf32-mep-little"
747 
748 #define elf_info_to_howto_rel			NULL
749 #define elf_info_to_howto			mep_info_to_howto_rela
750 #define elf_backend_relocate_section		mep_elf_relocate_section
751 #define elf_backend_object_p			mep_elf_object_p
752 #define elf_backend_section_flags		mep_elf_section_flags
753 #define elf_backend_fake_sections		mep_elf_fake_sections
754 
755 #define bfd_elf32_bfd_reloc_type_lookup		mep_reloc_type_lookup
756 #define bfd_elf32_bfd_reloc_name_lookup		mep_reloc_name_lookup
757 #define bfd_elf32_bfd_set_private_flags		mep_elf_set_private_flags
758 #define bfd_elf32_bfd_merge_private_bfd_data	mep_elf_merge_private_bfd_data
759 #define bfd_elf32_bfd_print_private_bfd_data	mep_elf_print_private_bfd_data
760 
761 #define elf_backend_rela_normal			1
762 
763 #include "elf32-target.h"
764