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
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       switch (r_type)
517         {
518         case R_RELC:
519           bfd_elf_perform_complex_relocation (input_bfd, input_section,
520                                               contents, rel, relocation);
521           continue;
522
523         default:
524           r = mep_final_link_relocate (howto, input_bfd, input_section,
525                                          contents, rel, relocation);
526           break;
527         }
528
529       if (r != bfd_reloc_ok)
530         {
531           const char * msg = (const char *) NULL;
532
533           switch (r)
534             {
535             case bfd_reloc_overflow:
536               r = info->callbacks->reloc_overflow
537                 (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
538                  input_bfd, input_section, rel->r_offset);
539               break;
540
541             case bfd_reloc_undefined:
542               r = info->callbacks->undefined_symbol
543                 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
544               break;
545
546             case bfd_reloc_outofrange:
547               msg = _("internal error: out of range error");
548               break;
549
550             case bfd_reloc_notsupported:
551               msg = _("internal error: unsupported relocation error");
552               break;
553
554             case bfd_reloc_dangerous:
555               msg = _("internal error: dangerous relocation");
556               break;
557
558             default:
559               msg = _("internal error: unknown error");
560               break;
561             }
562
563           if (msg)
564             r = info->callbacks->warning
565               (info, msg, name, input_bfd, input_section, rel->r_offset);
566
567           if (! r)
568             return FALSE;
569         }
570     }
571
572   if (warn_tp)
573     info->callbacks->undefined_symbol
574       (info, "__tpbase", input_bfd, input_section, warn_tp-1, TRUE);
575   if (warn_sda)
576     info->callbacks->undefined_symbol
577       (info, "__sdabase", input_bfd, input_section, warn_sda-1, TRUE);
578   if (warn_sda || warn_tp)
579     return FALSE;
580
581   return TRUE;
582 }
583 \f
584 /* Function to set the ELF flag bits.  */
585
586 static bfd_boolean
587 mep_elf_set_private_flags (bfd *    abfd,
588                            flagword flags)
589 {
590   elf_elfheader (abfd)->e_flags = flags;
591   elf_flags_init (abfd) = TRUE;
592   return TRUE;
593 }
594
595 static bfd_boolean
596 mep_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
597 {
598   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
599       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
600     return TRUE;
601
602   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
603   elf_flags_init (obfd) = TRUE;
604
605   /* Copy object attributes.  */
606   _bfd_elf_copy_obj_attributes (ibfd, obfd);
607
608   return TRUE;
609 }
610
611 /* Merge backend specific data from an object file to the output
612    object file when linking.  */
613
614 static bfd_boolean
615 mep_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
616 {
617   static bfd *last_ibfd = 0;
618   flagword old_flags, new_flags;
619   flagword old_partial, new_partial;
620
621   /* Check if we have the same endianess.  */
622   if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
623     return FALSE;
624
625   new_flags = elf_elfheader (ibfd)->e_flags;
626   old_flags = elf_elfheader (obfd)->e_flags;
627
628 #ifdef DEBUG
629   _bfd_error_handler ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s",
630                       ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
631 #endif
632
633     /* First call, no flags set.  */
634     if (!elf_flags_init (obfd))
635     {
636       elf_flags_init (obfd) = TRUE;
637       old_flags = new_flags;
638     }
639   else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
640     {
641       /* Non-library flags trump library flags.  The choice doesn't really
642          matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
643       if (old_flags & EF_MEP_LIBRARY)
644         old_flags = new_flags;
645     }
646   else
647     {
648       /* Make sure they're for the same mach.  Allow upgrade from the "mep"
649          mach.  */
650       new_partial = (new_flags & EF_MEP_CPU_MASK);
651       old_partial = (old_flags & EF_MEP_CPU_MASK);
652       if (new_partial == old_partial)
653         ;
654       else if (new_partial == EF_MEP_CPU_MEP)
655         ;
656       else if (old_partial == EF_MEP_CPU_MEP)
657         old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
658       else
659         {
660           _bfd_error_handler (_("%B and %B are for different cores"), last_ibfd, ibfd);
661           bfd_set_error (bfd_error_invalid_target);
662           return FALSE;
663         }
664
665       /* Make sure they're for the same me_module.  Allow basic config to
666          mix with any other.  */
667       new_partial = (new_flags & EF_MEP_INDEX_MASK);
668       old_partial = (old_flags & EF_MEP_INDEX_MASK);
669       if (new_partial == old_partial)
670         ;
671       else if (new_partial == 0)
672         ;
673       else if (old_partial == 0)
674         old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
675       else
676         {
677           _bfd_error_handler (_("%B and %B are for different configurations"), last_ibfd, ibfd);
678           bfd_set_error (bfd_error_invalid_target);
679           return FALSE;
680         }
681     }
682
683   elf_elfheader (obfd)->e_flags = old_flags;
684   last_ibfd = ibfd;
685   return TRUE;
686 }
687
688 /* This will be edited by the MeP configration tool.  */
689 static const char * config_names[] =
690 {
691   "basic"
692   /* start-mepcfgtool */
693   ,"simple"
694   ,"fmax"
695   /* end-mepcfgtool */
696 };
697
698 static const char * core_names[] =
699 {
700   "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
701 };
702
703 static bfd_boolean
704 mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
705 {
706   FILE *   file = (FILE *) ptr;
707   flagword flags, partial_flags;
708
709   BFD_ASSERT (abfd != NULL && ptr != NULL);
710
711   /* Print normal ELF private data.  */
712   _bfd_elf_print_private_bfd_data (abfd, ptr);
713
714   flags = elf_elfheader (abfd)->e_flags;
715   fprintf (file, _("private flags = 0x%lx"), (long)flags);
716
717   partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
718   if (partial_flags < ARRAY_SIZE (core_names))
719     fprintf (file, "  core: %s", core_names[(long)partial_flags]);
720
721   partial_flags = flags & EF_MEP_INDEX_MASK;
722   if (partial_flags < ARRAY_SIZE (config_names))
723     fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);
724
725   fputc ('\n', file);
726
727   return TRUE;
728 }
729
730 /* Return the machine subcode from the ELF e_flags header.  */
731
732 static int
733 elf32_mep_machine (bfd * abfd)
734 {
735   switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
736     {
737     default: break;
738     case EF_MEP_CPU_C2: return bfd_mach_mep;
739     case EF_MEP_CPU_C3: return bfd_mach_mep;
740     case EF_MEP_CPU_C4: return bfd_mach_mep;
741     case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
742     }
743
744   return bfd_mach_mep;
745 }
746
747 static bfd_boolean
748 mep_elf_object_p (bfd * abfd)
749 {
750   bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
751   return TRUE;
752 }
753
754 static bfd_boolean
755 mep_elf_section_flags (flagword * flags, const Elf_Internal_Shdr * hdr)
756 {
757   if (hdr->sh_flags & SHF_MEP_VLIW)
758     * flags |= SEC_MEP_VLIW;
759   return TRUE;
760 }
761
762 static bfd_boolean
763 mep_elf_fake_sections (bfd *               abfd ATTRIBUTE_UNUSED,
764                        Elf_Internal_Shdr * hdr,
765                        asection *          sec)
766 {
767   if (sec->flags & SEC_MEP_VLIW)
768     hdr->sh_flags |= SHF_MEP_VLIW;
769   return TRUE;
770 }
771
772 \f
773 #define ELF_ARCH                bfd_arch_mep
774 #define ELF_MACHINE_CODE        EM_CYGNUS_MEP
775 #define ELF_MAXPAGESIZE         0x1000
776
777 #define TARGET_BIG_SYM          bfd_elf32_mep_vec
778 #define TARGET_BIG_NAME         "elf32-mep"
779
780 #define TARGET_LITTLE_SYM       bfd_elf32_mep_little_vec
781 #define TARGET_LITTLE_NAME      "elf32-mep-little"
782
783 #define elf_info_to_howto_rel                   NULL
784 #define elf_info_to_howto                       mep_info_to_howto_rela
785 #define elf_backend_relocate_section            mep_elf_relocate_section
786 #define elf_backend_object_p                    mep_elf_object_p
787 #define elf_backend_section_flags               mep_elf_section_flags
788 #define elf_backend_fake_sections               mep_elf_fake_sections
789
790 #define bfd_elf32_bfd_reloc_type_lookup         mep_reloc_type_lookup
791 #define bfd_elf32_bfd_reloc_name_lookup         mep_reloc_name_lookup
792 #define bfd_elf32_bfd_set_private_flags         mep_elf_set_private_flags
793 #define bfd_elf32_bfd_copy_private_bfd_data     mep_elf_copy_private_bfd_data
794 #define bfd_elf32_bfd_merge_private_bfd_data    mep_elf_merge_private_bfd_data
795 #define bfd_elf32_bfd_print_private_bfd_data    mep_elf_print_private_bfd_data
796
797 #define elf_backend_rela_normal                 1
798
799 #include "elf32-target.h"