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