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