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