1 /* MeP-specific support for 32-bit ELF.
2    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
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 
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       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 
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 
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 
406 /* Relocate a MEP ELF section.
407    There is some attempt to make this function usable for many architectures,
408    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
409    if only to serve as a learning tool.
410 
411    The RELOCATE_SECTION function is called by the new ELF backend linker
412    to handle the relocations for a section.
413 
414    The relocs are always passed as Rela structures; if the section
415    actually uses Rel structures, the r_addend field will always be
416    zero.
417 
418    This function is responsible for adjusting the section contents as
419    necessary, and (if using Rela relocs and generating a relocatable
420    output file) adjusting the reloc addend as necessary.
421 
422    This function does not have to worry about setting the reloc
423    address or the reloc symbol index.
424 
425    LOCAL_SYMS is a pointer to the swapped in local symbols.
426 
427    LOCAL_SECTIONS is an array giving the section in the input file
428    corresponding to the st_shndx field of each local symbol.
429 
430    The global hash table entry for the global symbols can be found
431    via elf_sym_hashes (input_bfd).
432 
433    When generating relocatable output, this function must handle
434    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
435    going to be the section symbol corresponding to the output
436    section, which means that the addend must be adjusted
437    accordingly.  */
438 
439 static bfd_boolean
440 mep_elf_relocate_section
441     (bfd *                   output_bfd ATTRIBUTE_UNUSED,
442      struct bfd_link_info *  info,
443      bfd *                   input_bfd,
444      asection *              input_section,
445      bfd_byte *              contents,
446      Elf_Internal_Rela *     relocs,
447      Elf_Internal_Sym *      local_syms,
448      asection **             local_sections)
449 {
450   Elf_Internal_Shdr *           symtab_hdr;
451   struct elf_link_hash_entry ** sym_hashes;
452   Elf_Internal_Rela *           rel;
453   Elf_Internal_Rela *           relend;
454 
455   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
456   sym_hashes = elf_sym_hashes (input_bfd);
457   relend     = relocs + input_section->reloc_count;
458 
459   mep_info = info;
460 
461   for (rel = relocs; rel < relend; rel ++)
462     {
463       reloc_howto_type *           howto;
464       unsigned long                r_symndx;
465       Elf_Internal_Sym *           sym;
466       asection *                   sec;
467       struct elf_link_hash_entry * h;
468       bfd_vma                      relocation;
469       bfd_reloc_status_type        r;
470       const char *                 name = NULL;
471       int                          r_type;
472 
473       r_type = ELF32_R_TYPE (rel->r_info);
474       r_symndx = ELF32_R_SYM (rel->r_info);
475       howto  = mep_elf_howto_table + ELF32_R_TYPE (rel->r_info);
476       h      = NULL;
477       sym    = NULL;
478       sec    = NULL;
479 
480       if (r_symndx < symtab_hdr->sh_info)
481 	{
482 	  sym = local_syms + r_symndx;
483 	  sec = local_sections [r_symndx];
484 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
485 
486 	  name = bfd_elf_string_from_elf_section
487 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
488 	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
489 	}
490       else
491 	{
492 	  bfd_boolean warned, unresolved_reloc;
493 
494 	  RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel,
495 				  r_symndx, symtab_hdr, sym_hashes,
496 				  h, sec, relocation,
497 				  unresolved_reloc, warned);
498 
499 	  name = h->root.root.string;
500 	}
501 
502       if (sec != NULL && elf_discarded_section (sec))
503 	{
504 	  /* For relocs against symbols from removed linkonce sections,
505 	     or sections discarded by a linker script, we just want the
506 	     section contents zeroed.  Avoid any special processing.  */
507 	  _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
508 	  rel->r_info = 0;
509 	  rel->r_addend = 0;
510 	  continue;
511 	}
512 
513       if (info->relocatable)
514 	continue;
515 
516       if (r_type == R_RELC)
517 	r = bfd_elf_perform_complex_relocation (input_bfd, input_section,
518 						contents, rel, relocation);
519       else
520 	r = mep_final_link_relocate (howto, input_bfd, input_section,
521 				     contents, rel, relocation);
522 
523       if (r != bfd_reloc_ok)
524 	{
525 	  const char * msg = (const char *) NULL;
526 
527 	  switch (r)
528 	    {
529 	    case bfd_reloc_overflow:
530 	      r = info->callbacks->reloc_overflow
531 		(info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
532 		 input_bfd, input_section, rel->r_offset);
533 	      break;
534 
535 	    case bfd_reloc_undefined:
536 	      r = info->callbacks->undefined_symbol
537 		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
538 	      break;
539 
540 	    case bfd_reloc_outofrange:
541 	      msg = _("internal error: out of range error");
542 	      break;
543 
544 	    case bfd_reloc_notsupported:
545 	      msg = _("internal error: unsupported relocation error");
546 	      break;
547 
548 	    case bfd_reloc_dangerous:
549 	      msg = _("internal error: dangerous relocation");
550 	      break;
551 
552 	    default:
553 	      msg = _("internal error: unknown error");
554 	      break;
555 	    }
556 
557 	  if (msg)
558 	    r = info->callbacks->warning
559 	      (info, msg, name, input_bfd, input_section, rel->r_offset);
560 
561 	  if (! r)
562 	    return FALSE;
563 	}
564     }
565 
566   if (warn_tp)
567     info->callbacks->undefined_symbol
568       (info, "__tpbase", input_bfd, input_section, warn_tp-1, TRUE);
569   if (warn_sda)
570     info->callbacks->undefined_symbol
571       (info, "__sdabase", input_bfd, input_section, warn_sda-1, TRUE);
572   if (warn_sda || warn_tp)
573     return FALSE;
574 
575   return TRUE;
576 }
577 
578 /* Function to set the ELF flag bits.  */
579 
580 static bfd_boolean
581 mep_elf_set_private_flags (bfd *    abfd,
582 			   flagword flags)
583 {
584   elf_elfheader (abfd)->e_flags = flags;
585   elf_flags_init (abfd) = TRUE;
586   return TRUE;
587 }
588 
589 static bfd_boolean
590 mep_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
591 {
592   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
593       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
594     return TRUE;
595 
596   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
597   elf_flags_init (obfd) = TRUE;
598 
599   /* Copy object attributes.  */
600   _bfd_elf_copy_obj_attributes (ibfd, obfd);
601 
602   return TRUE;
603 }
604 
605 /* Merge backend specific data from an object file to the output
606    object file when linking.  */
607 
608 static bfd_boolean
609 mep_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
610 {
611   static bfd *last_ibfd = 0;
612   flagword old_flags, new_flags;
613   flagword old_partial, new_partial;
614 
615   /* Check if we have the same endianess.  */
616   if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
617     return FALSE;
618 
619   new_flags = elf_elfheader (ibfd)->e_flags;
620   old_flags = elf_elfheader (obfd)->e_flags;
621 
622 #ifdef DEBUG
623   _bfd_error_handler ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s",
624 		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
625 #endif
626 
627     /* First call, no flags set.  */
628     if (!elf_flags_init (obfd))
629     {
630       elf_flags_init (obfd) = TRUE;
631       old_flags = new_flags;
632     }
633   else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
634     {
635       /* Non-library flags trump library flags.  The choice doesn't really
636 	 matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
637       if (old_flags & EF_MEP_LIBRARY)
638 	old_flags = new_flags;
639     }
640   else
641     {
642       /* Make sure they're for the same mach.  Allow upgrade from the "mep"
643 	 mach.  */
644       new_partial = (new_flags & EF_MEP_CPU_MASK);
645       old_partial = (old_flags & EF_MEP_CPU_MASK);
646       if (new_partial == old_partial)
647 	;
648       else if (new_partial == EF_MEP_CPU_MEP)
649 	;
650       else if (old_partial == EF_MEP_CPU_MEP)
651 	old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
652       else
653 	{
654 	  _bfd_error_handler (_("%B and %B are for different cores"), last_ibfd, ibfd);
655 	  bfd_set_error (bfd_error_invalid_target);
656 	  return FALSE;
657 	}
658 
659       /* Make sure they're for the same me_module.  Allow basic config to
660 	 mix with any other.  */
661       new_partial = (new_flags & EF_MEP_INDEX_MASK);
662       old_partial = (old_flags & EF_MEP_INDEX_MASK);
663       if (new_partial == old_partial)
664 	;
665       else if (new_partial == 0)
666 	;
667       else if (old_partial == 0)
668 	old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
669       else
670 	{
671 	  _bfd_error_handler (_("%B and %B are for different configurations"), last_ibfd, ibfd);
672 	  bfd_set_error (bfd_error_invalid_target);
673 	  return FALSE;
674 	}
675     }
676 
677   elf_elfheader (obfd)->e_flags = old_flags;
678   last_ibfd = ibfd;
679   return TRUE;
680 }
681 
682 /* This will be edited by the MeP configration tool.  */
683 static const char * config_names[] =
684 {
685   "basic"
686   /* start-mepcfgtool */
687   ,"simple"
688   ,"fmax"
689   /* end-mepcfgtool */
690 };
691 
692 static const char * core_names[] =
693 {
694   "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
695 };
696 
697 static bfd_boolean
698 mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
699 {
700   FILE *   file = (FILE *) ptr;
701   flagword flags, partial_flags;
702 
703   BFD_ASSERT (abfd != NULL && ptr != NULL);
704 
705   /* Print normal ELF private data.  */
706   _bfd_elf_print_private_bfd_data (abfd, ptr);
707 
708   flags = elf_elfheader (abfd)->e_flags;
709   fprintf (file, _("private flags = 0x%lx"), (unsigned long) flags);
710 
711   partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
712   if (partial_flags < ARRAY_SIZE (core_names))
713     fprintf (file, "  core: %s", core_names[(long)partial_flags]);
714 
715   partial_flags = flags & EF_MEP_INDEX_MASK;
716   if (partial_flags < ARRAY_SIZE (config_names))
717     fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);
718 
719   fputc ('\n', file);
720 
721   return TRUE;
722 }
723 
724 /* Return the machine subcode from the ELF e_flags header.  */
725 
726 static int
727 elf32_mep_machine (bfd * abfd)
728 {
729   switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
730     {
731     default: break;
732     case EF_MEP_CPU_C2: return bfd_mach_mep;
733     case EF_MEP_CPU_C3: return bfd_mach_mep;
734     case EF_MEP_CPU_C4: return bfd_mach_mep;
735     case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
736     }
737 
738   return bfd_mach_mep;
739 }
740 
741 static bfd_boolean
742 mep_elf_object_p (bfd * abfd)
743 {
744   bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
745   return TRUE;
746 }
747 
748 static bfd_boolean
749 mep_elf_section_flags (flagword * flags, const Elf_Internal_Shdr * hdr)
750 {
751   if (hdr->sh_flags & SHF_MEP_VLIW)
752     * flags |= SEC_MEP_VLIW;
753   return TRUE;
754 }
755 
756 static bfd_boolean
757 mep_elf_fake_sections (bfd *               abfd ATTRIBUTE_UNUSED,
758 		       Elf_Internal_Shdr * hdr,
759 		       asection *          sec)
760 {
761   if (sec->flags & SEC_MEP_VLIW)
762     hdr->sh_flags |= SHF_MEP_VLIW;
763   return TRUE;
764 }
765 
766 
767 #define ELF_ARCH		bfd_arch_mep
768 #define ELF_MACHINE_CODE	EM_CYGNUS_MEP
769 #define ELF_MAXPAGESIZE		0x1000
770 
771 #define TARGET_BIG_SYM		bfd_elf32_mep_vec
772 #define TARGET_BIG_NAME		"elf32-mep"
773 
774 #define TARGET_LITTLE_SYM	bfd_elf32_mep_little_vec
775 #define TARGET_LITTLE_NAME	"elf32-mep-little"
776 
777 #define elf_info_to_howto_rel			NULL
778 #define elf_info_to_howto			mep_info_to_howto_rela
779 #define elf_backend_relocate_section		mep_elf_relocate_section
780 #define elf_backend_object_p		        mep_elf_object_p
781 #define elf_backend_section_flags		mep_elf_section_flags
782 #define elf_backend_fake_sections		mep_elf_fake_sections
783 
784 #define bfd_elf32_bfd_reloc_type_lookup		mep_reloc_type_lookup
785 #define bfd_elf32_bfd_reloc_name_lookup		mep_reloc_name_lookup
786 #define bfd_elf32_bfd_set_private_flags		mep_elf_set_private_flags
787 #define bfd_elf32_bfd_copy_private_bfd_data	mep_elf_copy_private_bfd_data
788 #define bfd_elf32_bfd_merge_private_bfd_data	mep_elf_merge_private_bfd_data
789 #define bfd_elf32_bfd_print_private_bfd_data	mep_elf_print_private_bfd_data
790 
791 #define elf_backend_rela_normal			1
792 
793 #include "elf32-target.h"
794