OSDN Git Service

bfd/
[pf3gnuchains/pf3gnuchains3x.git] / bfd / elf32-mep.c
1 /* MeP-specific support for 32-bit ELF.
2    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
3    Free Software Foundation, Inc.
4
5    This file is part of BFD, the Binary File Descriptor library.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21
22 #include "sysdep.h"
23 #include "bfd.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/mep.h"
27 #include "libiberty.h"
28
29 /* Forward declarations.  */
30
31 /* Private relocation functions.  */
32 \f
33 #define MEPREL(type, size, bits, right, left, pcrel, overflow, mask) \
34   {(unsigned)type, right, size, bits, pcrel, left, overflow, mep_reloc, #type, FALSE, 0, mask, 0 }
35
36 #define N complain_overflow_dont
37 #define S complain_overflow_signed
38 #define U complain_overflow_unsigned
39
40 static bfd_reloc_status_type mep_reloc (bfd *, arelent *, struct bfd_symbol *,
41                                         void *, asection *, bfd *, char **);
42
43 static reloc_howto_type mep_elf_howto_table [] =
44 {
45   /* type, size, bits, leftshift, rightshift, pcrel, OD/OS/OU, mask.  */
46   MEPREL (R_MEP_NONE,     0,  0, 0, 0, 0, N, 0),
47   MEPREL (R_RELC,         0,  0, 0, 0, 0, N, 0),
48   /* MEPRELOC:HOWTO */
49     /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
50   MEPREL (R_MEP_8,        0,  8, 0, 0, 0, U, 0xff),
51   MEPREL (R_MEP_16,       1, 16, 0, 0, 0, U, 0xffff),
52   MEPREL (R_MEP_32,       2, 32, 0, 0, 0, U, 0xffffffff),
53   MEPREL (R_MEP_PCREL8A2, 1,  8, 1, 1, 1, S, 0x00fe),
54   MEPREL (R_MEP_PCREL12A2,1, 12, 1, 1, 1, S, 0x0ffe),
55   MEPREL (R_MEP_PCREL17A2,2, 17, 0, 1, 1, S, 0x0000ffff),
56   MEPREL (R_MEP_PCREL24A2,2, 24, 0, 1, 1, S, 0x07f0ffff),
57   MEPREL (R_MEP_PCABS24A2,2, 24, 0, 1, 0, U, 0x07f0ffff),
58   MEPREL (R_MEP_LOW16,    2, 16, 0, 0, 0, N, 0x0000ffff),
59   MEPREL (R_MEP_HI16U,    2, 32, 0,16, 0, N, 0x0000ffff),
60   MEPREL (R_MEP_HI16S,    2, 32, 0,16, 0, N, 0x0000ffff),
61   MEPREL (R_MEP_GPREL,    2, 16, 0, 0, 0, S, 0x0000ffff),
62   MEPREL (R_MEP_TPREL,    2, 16, 0, 0, 0, S, 0x0000ffff),
63   MEPREL (R_MEP_TPREL7,   1,  7, 0, 0, 0, U, 0x007f),
64   MEPREL (R_MEP_TPREL7A2, 1,  7, 1, 1, 0, U, 0x007e),
65   MEPREL (R_MEP_TPREL7A4, 1,  7, 2, 2, 0, U, 0x007c),
66   MEPREL (R_MEP_UIMM24,   2, 24, 0, 0, 0, U, 0x00ffffff),
67   MEPREL (R_MEP_ADDR24A4, 2, 24, 0, 2, 0, U, 0x00fcffff),
68   MEPREL (R_MEP_GNU_VTINHERIT,1,  0,16,32, 0, N, 0x0000),
69   MEPREL (R_MEP_GNU_VTENTRY,1,  0,16,32, 0, N, 0x0000),
70   /* MEPRELOC:END */
71 };
72
73 #define VALID_MEP_RELOC(N) ((N) >= 0 \
74   && (N) < ARRAY_SIZE (mep_elf_howto_table)
75
76 #undef N
77 #undef S
78 #undef U
79
80 static bfd_reloc_status_type
81 mep_reloc
82     (bfd *               abfd ATTRIBUTE_UNUSED,
83      arelent *           reloc_entry ATTRIBUTE_UNUSED,
84      struct bfd_symbol * symbol ATTRIBUTE_UNUSED,
85      void *              data ATTRIBUTE_UNUSED,
86      asection *          input_section ATTRIBUTE_UNUSED,
87      bfd *               output_bfd ATTRIBUTE_UNUSED,
88      char **             error_message ATTRIBUTE_UNUSED)
89 {
90   return bfd_reloc_ok;
91 }
92
93 \f
94
95 #define BFD_RELOC_MEP_NONE BFD_RELOC_NONE
96 #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
97 #define MAP(n) case BFD_RELOC_MEP_##n: type = R_MEP_##n; break
98 #else
99 #define MAP(n) case BFD_RELOC_MEP_/**/n: type = R_MEP_/**/n; break
100 #endif
101
102 static reloc_howto_type *
103 mep_reloc_type_lookup
104     (bfd * abfd ATTRIBUTE_UNUSED,
105      bfd_reloc_code_real_type code)
106 {
107   unsigned int type = 0;
108
109   switch (code)
110     {
111     MAP(NONE);
112     case BFD_RELOC_8:
113       type = R_MEP_8;
114       break;
115     case BFD_RELOC_16:
116       type = R_MEP_16;
117       break;
118     case BFD_RELOC_32:
119       type = R_MEP_32;
120       break;
121     case BFD_RELOC_VTABLE_ENTRY:
122       type = R_MEP_GNU_VTENTRY;
123       break;
124     case BFD_RELOC_VTABLE_INHERIT:
125       type = R_MEP_GNU_VTINHERIT;
126       break;
127     case BFD_RELOC_RELC:
128       type = R_RELC;
129       break;
130
131     /* MEPRELOC:MAP */
132     /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
133     MAP(8);
134     MAP(16);
135     MAP(32);
136     MAP(PCREL8A2);
137     MAP(PCREL12A2);
138     MAP(PCREL17A2);
139     MAP(PCREL24A2);
140     MAP(PCABS24A2);
141     MAP(LOW16);
142     MAP(HI16U);
143     MAP(HI16S);
144     MAP(GPREL);
145     MAP(TPREL);
146     MAP(TPREL7);
147     MAP(TPREL7A2);
148     MAP(TPREL7A4);
149     MAP(UIMM24);
150     MAP(ADDR24A4);
151     MAP(GNU_VTINHERIT);
152     MAP(GNU_VTENTRY);
153     /* MEPRELOC:END */
154
155     default:
156       /* Pacify gcc -Wall.  */
157       fprintf (stderr, "mep: no reloc for code %d\n", code);
158       return NULL;
159     }
160
161   if (mep_elf_howto_table[type].type != type)
162     {
163       fprintf (stderr, "MeP: howto %d has type %d\n", 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;
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);
498
499           name = h->root.root.string;
500         }
501
502       if (sec != NULL && elf_discarded_section (sec))
503         {
504           /* For relocs against symbols from removed linkonce sections,
505              or sections discarded by a linker script, we just want the
506              section contents zeroed.  Avoid any special processing.  */
507           _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
508           rel->r_info = 0;
509           rel->r_addend = 0;
510           continue;
511         }
512
513       if (info->relocatable)
514         continue;
515
516       if (r_type == R_RELC)
517         r = bfd_elf_perform_complex_relocation (input_bfd, input_section,
518                                                 contents, rel, relocation);
519       else
520         r = mep_final_link_relocate (howto, input_bfd, input_section,
521                                      contents, rel, relocation);
522
523       if (r != bfd_reloc_ok)
524         {
525           const char * msg = (const char *) NULL;
526
527           switch (r)
528             {
529             case bfd_reloc_overflow:
530               r = info->callbacks->reloc_overflow
531                 (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
532                  input_bfd, input_section, rel->r_offset);
533               break;
534
535             case bfd_reloc_undefined:
536               r = info->callbacks->undefined_symbol
537                 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
538               break;
539
540             case bfd_reloc_outofrange:
541               msg = _("internal error: out of range error");
542               break;
543
544             case bfd_reloc_notsupported:
545               msg = _("internal error: unsupported relocation error");
546               break;
547
548             case bfd_reloc_dangerous:
549               msg = _("internal error: dangerous relocation");
550               break;
551
552             default:
553               msg = _("internal error: unknown error");
554               break;
555             }
556
557           if (msg)
558             r = info->callbacks->warning
559               (info, msg, name, input_bfd, input_section, rel->r_offset);
560
561           if (! r)
562             return FALSE;
563         }
564     }
565
566   if (warn_tp)
567     info->callbacks->undefined_symbol
568       (info, "__tpbase", input_bfd, input_section, warn_tp-1, TRUE);
569   if (warn_sda)
570     info->callbacks->undefined_symbol
571       (info, "__sdabase", input_bfd, input_section, warn_sda-1, TRUE);
572   if (warn_sda || warn_tp)
573     return FALSE;
574
575   return TRUE;
576 }
577 \f
578 /* Function to set the ELF flag bits.  */
579
580 static bfd_boolean
581 mep_elf_set_private_flags (bfd *    abfd,
582                            flagword flags)
583 {
584   elf_elfheader (abfd)->e_flags = flags;
585   elf_flags_init (abfd) = TRUE;
586   return TRUE;
587 }
588
589 static bfd_boolean
590 mep_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
591 {
592   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
593       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
594     return TRUE;
595
596   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
597   elf_flags_init (obfd) = TRUE;
598
599   /* Copy object attributes.  */
600   _bfd_elf_copy_obj_attributes (ibfd, obfd);
601
602   return TRUE;
603 }
604
605 /* Merge backend specific data from an object file to the output
606    object file when linking.  */
607
608 static bfd_boolean
609 mep_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
610 {
611   static bfd *last_ibfd = 0;
612   flagword old_flags, new_flags;
613   flagword old_partial, new_partial;
614
615   /* Check if we have the same endianess.  */
616   if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
617     return FALSE;
618
619   new_flags = elf_elfheader (ibfd)->e_flags;
620   old_flags = elf_elfheader (obfd)->e_flags;
621
622 #ifdef DEBUG
623   _bfd_error_handler ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s",
624                       ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
625 #endif
626
627     /* First call, no flags set.  */
628     if (!elf_flags_init (obfd))
629     {
630       elf_flags_init (obfd) = TRUE;
631       old_flags = new_flags;
632     }
633   else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
634     {
635       /* Non-library flags trump library flags.  The choice doesn't really
636          matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
637       if (old_flags & EF_MEP_LIBRARY)
638         old_flags = new_flags;
639     }
640   else
641     {
642       /* Make sure they're for the same mach.  Allow upgrade from the "mep"
643          mach.  */
644       new_partial = (new_flags & EF_MEP_CPU_MASK);
645       old_partial = (old_flags & EF_MEP_CPU_MASK);
646       if (new_partial == old_partial)
647         ;
648       else if (new_partial == EF_MEP_CPU_MEP)
649         ;
650       else if (old_partial == EF_MEP_CPU_MEP)
651         old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
652       else
653         {
654           _bfd_error_handler (_("%B and %B are for different cores"), last_ibfd, ibfd);
655           bfd_set_error (bfd_error_invalid_target);
656           return FALSE;
657         }
658
659       /* Make sure they're for the same me_module.  Allow basic config to
660          mix with any other.  */
661       new_partial = (new_flags & EF_MEP_INDEX_MASK);
662       old_partial = (old_flags & EF_MEP_INDEX_MASK);
663       if (new_partial == old_partial)
664         ;
665       else if (new_partial == 0)
666         ;
667       else if (old_partial == 0)
668         old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
669       else
670         {
671           _bfd_error_handler (_("%B and %B are for different configurations"), last_ibfd, ibfd);
672           bfd_set_error (bfd_error_invalid_target);
673           return FALSE;
674         }
675     }
676
677   elf_elfheader (obfd)->e_flags = old_flags;
678   last_ibfd = ibfd;
679   return TRUE;
680 }
681
682 /* This will be edited by the MeP configration tool.  */
683 static const char * config_names[] =
684 {
685   "basic"
686   /* start-mepcfgtool */
687   ,"default"
688   /* end-mepcfgtool */
689 };
690
691 static const char * core_names[] =
692 {
693   "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
694 };
695
696 static bfd_boolean
697 mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
698 {
699   FILE *   file = (FILE *) ptr;
700   flagword flags, partial_flags;
701
702   BFD_ASSERT (abfd != NULL && ptr != NULL);
703
704   /* Print normal ELF private data.  */
705   _bfd_elf_print_private_bfd_data (abfd, ptr);
706
707   flags = elf_elfheader (abfd)->e_flags;
708   fprintf (file, _("private flags = 0x%lx"), (unsigned long) flags);
709
710   partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
711   if (partial_flags < ARRAY_SIZE (core_names))
712     fprintf (file, "  core: %s", core_names[(long)partial_flags]);
713
714   partial_flags = flags & EF_MEP_INDEX_MASK;
715   if (partial_flags < ARRAY_SIZE (config_names))
716     fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);
717
718   fputc ('\n', file);
719
720   return TRUE;
721 }
722
723 /* Return the machine subcode from the ELF e_flags header.  */
724
725 static int
726 elf32_mep_machine (bfd * abfd)
727 {
728   switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
729     {
730     default: break;
731     case EF_MEP_CPU_C2: return bfd_mach_mep;
732     case EF_MEP_CPU_C3: return bfd_mach_mep;
733     case EF_MEP_CPU_C4: return bfd_mach_mep;
734     case EF_MEP_CPU_C5: return bfd_mach_mep_c5;
735     case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
736     }
737
738   return bfd_mach_mep;
739 }
740
741 static bfd_boolean
742 mep_elf_object_p (bfd * abfd)
743 {
744   bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
745   return TRUE;
746 }
747
748 static bfd_boolean
749 mep_elf_section_flags (flagword * flags, const Elf_Internal_Shdr * hdr)
750 {
751   if (hdr->sh_flags & SHF_MEP_VLIW)
752     * flags |= SEC_MEP_VLIW;
753   return TRUE;
754 }
755
756 static bfd_boolean
757 mep_elf_fake_sections (bfd *               abfd ATTRIBUTE_UNUSED,
758                        Elf_Internal_Shdr * hdr,
759                        asection *          sec)
760 {
761   if (sec->flags & SEC_MEP_VLIW)
762     hdr->sh_flags |= SHF_MEP_VLIW;
763   return TRUE;
764 }
765
766 \f
767 #define ELF_ARCH                bfd_arch_mep
768 #define ELF_MACHINE_CODE        EM_CYGNUS_MEP
769 #define ELF_MAXPAGESIZE         0x1000
770
771 #define TARGET_BIG_SYM          bfd_elf32_mep_vec
772 #define TARGET_BIG_NAME         "elf32-mep"
773
774 #define TARGET_LITTLE_SYM       bfd_elf32_mep_little_vec
775 #define TARGET_LITTLE_NAME      "elf32-mep-little"
776
777 #define elf_info_to_howto_rel                   NULL
778 #define elf_info_to_howto                       mep_info_to_howto_rela
779 #define elf_backend_relocate_section            mep_elf_relocate_section
780 #define elf_backend_object_p                    mep_elf_object_p
781 #define elf_backend_section_flags               mep_elf_section_flags
782 #define elf_backend_fake_sections               mep_elf_fake_sections
783
784 #define bfd_elf32_bfd_reloc_type_lookup         mep_reloc_type_lookup
785 #define bfd_elf32_bfd_reloc_name_lookup         mep_reloc_name_lookup
786 #define bfd_elf32_bfd_set_private_flags         mep_elf_set_private_flags
787 #define bfd_elf32_bfd_copy_private_bfd_data     mep_elf_copy_private_bfd_data
788 #define bfd_elf32_bfd_merge_private_bfd_data    mep_elf_merge_private_bfd_data
789 #define bfd_elf32_bfd_print_private_bfd_data    mep_elf_print_private_bfd_data
790
791 #define elf_backend_rela_normal                 1
792
793 #include "elf32-target.h"