1/* MeP-specific support for 32-bit ELF.
2   Copyright (C) 2001-2022 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
39static 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
84static reloc_howto_type *
85mep_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
156static reloc_howto_type *
157mep_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
173static struct bfd_link_info *mep_info;
174static int warn_tp = 0, warn_sda = 0;
175
176static bfd_vma
177mep_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
200static bfd_vma
201mep_tpoff_base (bfd_vma ofs)
202{
203  static bfd_vma cache = 0;
204  return mep_lookup_global ("__tpbase", ofs, &cache, &warn_tp);
205}
206
207static bfd_vma
208mep_sdaoff_base (bfd_vma ofs)
209{
210  static bfd_vma cache = 0;
211  return mep_lookup_global ("__sdabase", ofs, &cache, &warn_sda);
212}
213
214static bfd_reloc_status_type
215mep_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
374static bool
375mep_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
427static int
428mep_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
558static bool
559mep_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
570static bool
571mep_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.  */
650static const char * config_names[] =
651{
652  "basic"
653  /* start-mepcfgtool */
654  ,"default"
655  /* end-mepcfgtool */
656};
657
658static const char * core_names[] =
659{
660  "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
661};
662
663static bool
664mep_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
692static int
693elf32_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
708static bool
709mep_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
715static bool
716mep_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
723static bool
724mep_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"
760