xref: /netbsd-src/external/gpl3/gdb/dist/bfd/elf32-mep.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
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 
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 
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 
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 
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 
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 
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 
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"
788