1/* MeP-specific support for 32-bit ELF.
2   Copyright (C) 2001-2017 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
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,     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
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  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
378static void
379mep_info_to_howto_rela
380    (bfd *               abfd ATTRIBUTE_UNUSED,
381     arelent *           cache_ptr,
382     Elf_Internal_Rela * dst)
383{
384  unsigned int r_type;
385
386  r_type = ELF32_R_TYPE (dst->r_info);
387  if (r_type >= R_MEP_max)
388    {
389      /* xgettext:c-format */
390      _bfd_error_handler (_("%B: invalid MEP reloc number: %d"), abfd, r_type);
391      r_type = 0;
392    }
393  cache_ptr->howto = & mep_elf_howto_table [r_type];
394}
395
396/* Relocate a MEP ELF section.
397   There is some attempt to make this function usable for many architectures,
398   both USE_REL and USE_RELA ['twould be nice if such a critter existed],
399   if only to serve as a learning tool.
400
401   The RELOCATE_SECTION function is called by the new ELF backend linker
402   to handle the relocations for a section.
403
404   The relocs are always passed as Rela structures; if the section
405   actually uses Rel structures, the r_addend field will always be
406   zero.
407
408   This function is responsible for adjusting the section contents as
409   necessary, and (if using Rela relocs and generating a relocatable
410   output file) adjusting the reloc addend as necessary.
411
412   This function does not have to worry about setting the reloc
413   address or the reloc symbol index.
414
415   LOCAL_SYMS is a pointer to the swapped in local symbols.
416
417   LOCAL_SECTIONS is an array giving the section in the input file
418   corresponding to the st_shndx field of each local symbol.
419
420   The global hash table entry for the global symbols can be found
421   via elf_sym_hashes (input_bfd).
422
423   When generating relocatable output, this function must handle
424   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
425   going to be the section symbol corresponding to the output
426   section, which means that the addend must be adjusted
427   accordingly.  */
428
429static bfd_boolean
430mep_elf_relocate_section
431    (bfd *                   output_bfd ATTRIBUTE_UNUSED,
432     struct bfd_link_info *  info,
433     bfd *                   input_bfd,
434     asection *              input_section,
435     bfd_byte *              contents,
436     Elf_Internal_Rela *     relocs,
437     Elf_Internal_Sym *      local_syms,
438     asection **             local_sections)
439{
440  Elf_Internal_Shdr *           symtab_hdr;
441  struct elf_link_hash_entry ** sym_hashes;
442  Elf_Internal_Rela *           rel;
443  Elf_Internal_Rela *           relend;
444
445  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
446  sym_hashes = elf_sym_hashes (input_bfd);
447  relend     = relocs + input_section->reloc_count;
448
449  mep_info = info;
450
451  for (rel = relocs; rel < relend; rel ++)
452    {
453      reloc_howto_type *           howto;
454      unsigned long                r_symndx;
455      Elf_Internal_Sym *           sym;
456      asection *                   sec;
457      struct elf_link_hash_entry * h;
458      bfd_vma                      relocation;
459      bfd_reloc_status_type        r;
460      const char *                 name = NULL;
461      int                          r_type;
462
463      r_type = ELF32_R_TYPE (rel->r_info);
464      r_symndx = ELF32_R_SYM (rel->r_info);
465      howto  = mep_elf_howto_table + ELF32_R_TYPE (rel->r_info);
466      h      = NULL;
467      sym    = NULL;
468      sec    = NULL;
469
470      if (r_symndx < symtab_hdr->sh_info)
471	{
472	  sym = local_syms + r_symndx;
473	  sec = local_sections [r_symndx];
474	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
475
476	  name = bfd_elf_string_from_elf_section
477	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
478	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
479	}
480      else
481	{
482	  bfd_boolean warned, unresolved_reloc, ignored;
483
484	  RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel,
485				  r_symndx, symtab_hdr, sym_hashes,
486				  h, sec, relocation,
487				  unresolved_reloc, warned, ignored);
488
489	  name = h->root.root.string;
490	}
491
492      if (sec != NULL && discarded_section (sec))
493	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
494					 rel, 1, relend, howto, 0, contents);
495
496      if (bfd_link_relocatable (info))
497	continue;
498
499      if (r_type == R_RELC)
500	r = bfd_elf_perform_complex_relocation (input_bfd, input_section,
501						contents, rel, relocation);
502      else
503	r = mep_final_link_relocate (howto, input_bfd, input_section,
504				     contents, rel, relocation);
505
506      if (r != bfd_reloc_ok)
507	{
508	  const char * msg = (const char *) NULL;
509
510	  switch (r)
511	    {
512	    case bfd_reloc_overflow:
513	      (*info->callbacks->reloc_overflow)
514		(info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
515		 input_bfd, input_section, rel->r_offset);
516	      break;
517
518	    case bfd_reloc_undefined:
519	      (*info->callbacks->undefined_symbol)
520		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
521	      break;
522
523	    case bfd_reloc_outofrange:
524	      msg = _("internal error: out of range error");
525	      break;
526
527	    case bfd_reloc_notsupported:
528	      msg = _("internal error: unsupported relocation error");
529	      break;
530
531	    case bfd_reloc_dangerous:
532	      msg = _("internal error: dangerous relocation");
533	      break;
534
535	    default:
536	      msg = _("internal error: unknown error");
537	      break;
538	    }
539
540	  if (msg)
541	    (*info->callbacks->warning) (info, msg, name, input_bfd,
542					 input_section, rel->r_offset);
543	}
544    }
545
546  if (warn_tp)
547    info->callbacks->undefined_symbol
548      (info, "__tpbase", input_bfd, input_section, warn_tp-1, TRUE);
549  if (warn_sda)
550    info->callbacks->undefined_symbol
551      (info, "__sdabase", input_bfd, input_section, warn_sda-1, TRUE);
552  if (warn_sda || warn_tp)
553    return FALSE;
554
555  return TRUE;
556}
557
558/* Function to set the ELF flag bits.  */
559
560static bfd_boolean
561mep_elf_set_private_flags (bfd *    abfd,
562			   flagword flags)
563{
564  elf_elfheader (abfd)->e_flags = flags;
565  elf_flags_init (abfd) = TRUE;
566  return TRUE;
567}
568
569/* Merge backend specific data from an object file to the output
570   object file when linking.  */
571
572static bfd_boolean
573mep_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
574{
575  bfd *obfd = info->output_bfd;
576  static bfd *last_ibfd = 0;
577  flagword old_flags, new_flags;
578  flagword old_partial, new_partial;
579
580  /* Check if we have the same endianness.  */
581  if (!_bfd_generic_verify_endian_match (ibfd, info))
582    return FALSE;
583
584  new_flags = elf_elfheader (ibfd)->e_flags;
585  old_flags = elf_elfheader (obfd)->e_flags;
586
587#ifdef DEBUG
588  _bfd_error_handler ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s",
589		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
590#endif
591
592    /* First call, no flags set.  */
593    if (!elf_flags_init (obfd))
594    {
595      elf_flags_init (obfd) = TRUE;
596      old_flags = new_flags;
597    }
598  else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
599    {
600      /* Non-library flags trump library flags.  The choice doesn't really
601	 matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
602      if (old_flags & EF_MEP_LIBRARY)
603	old_flags = new_flags;
604    }
605  else
606    {
607      /* Make sure they're for the same mach.  Allow upgrade from the "mep"
608	 mach.  */
609      new_partial = (new_flags & EF_MEP_CPU_MASK);
610      old_partial = (old_flags & EF_MEP_CPU_MASK);
611      if (new_partial == old_partial)
612	;
613      else if (new_partial == EF_MEP_CPU_MEP)
614	;
615      else if (old_partial == EF_MEP_CPU_MEP)
616	old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
617      else
618	{
619	  /* xgettext:c-format */
620	  _bfd_error_handler (_("%B and %B are for different cores"), last_ibfd, ibfd);
621	  bfd_set_error (bfd_error_invalid_target);
622	  return FALSE;
623	}
624
625      /* Make sure they're for the same me_module.  Allow basic config to
626	 mix with any other.  */
627      new_partial = (new_flags & EF_MEP_INDEX_MASK);
628      old_partial = (old_flags & EF_MEP_INDEX_MASK);
629      if (new_partial == old_partial)
630	;
631      else if (new_partial == 0)
632	;
633      else if (old_partial == 0)
634	old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
635      else
636	{
637	  /* xgettext:c-format */
638	  _bfd_error_handler (_("%B and %B are for different configurations"), 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 bfd_boolean
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 bfd_boolean
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 bfd_boolean
716mep_elf_section_flags (flagword * flags, const Elf_Internal_Shdr * hdr)
717{
718  if (hdr->sh_flags & SHF_MEP_VLIW)
719    * flags |= SEC_MEP_VLIW;
720  return TRUE;
721}
722
723static bfd_boolean
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