1 /* MeP-specific support for 32-bit ELF.
2    Copyright (C) 2001-2021 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 
32 #define MEPREL(type, size, bits, right, left, pcrel, overflow, mask) \
33   HOWTO (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 
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 *
mep_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)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       /* xgettext:c-format */
146       _bfd_error_handler (_("MeP: howto %d has type %d"),
147 			  type, mep_elf_howto_table[type].type);
148       abort ();
149     }
150 
151   return mep_elf_howto_table + type;
152 }
153 
154 #undef MAP
155 
156 static reloc_howto_type *
mep_reloc_name_lookup(bfd * abfd ATTRIBUTE_UNUSED,const char * r_name)157 mep_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
158 {
159   unsigned int i;
160 
161   for (i = 0;
162        i < sizeof (mep_elf_howto_table) / sizeof (mep_elf_howto_table[0]);
163        i++)
164     if (mep_elf_howto_table[i].name != NULL
165 	&& strcasecmp (mep_elf_howto_table[i].name, r_name) == 0)
166       return &mep_elf_howto_table[i];
167 
168   return NULL;
169 }
170 
171 /* Perform a single relocation.  */
172 
173 static struct bfd_link_info *mep_info;
174 static int warn_tp = 0, warn_sda = 0;
175 
176 static bfd_vma
mep_lookup_global(char * name,bfd_vma ofs,bfd_vma * cache,int * warn)177 mep_lookup_global
178     (char *    name,
179      bfd_vma   ofs,
180      bfd_vma * cache,
181      int *     warn)
182 {
183   struct bfd_link_hash_entry *h;
184 
185   if (*cache || *warn)
186     return *cache;
187 
188   h = bfd_link_hash_lookup (mep_info->hash, name, false, false, true);
189   if (h == 0 || h->type != bfd_link_hash_defined)
190     {
191       *warn = ofs + 1;
192       return 0;
193     }
194   *cache = (h->u.def.value
195 	  + h->u.def.section->output_section->vma
196 	  + h->u.def.section->output_offset);
197   return *cache;
198 }
199 
200 static bfd_vma
mep_tpoff_base(bfd_vma ofs)201 mep_tpoff_base (bfd_vma ofs)
202 {
203   static bfd_vma cache = 0;
204   return mep_lookup_global ("__tpbase", ofs, &cache, &warn_tp);
205 }
206 
207 static bfd_vma
mep_sdaoff_base(bfd_vma ofs)208 mep_sdaoff_base (bfd_vma ofs)
209 {
210   static bfd_vma cache = 0;
211   return mep_lookup_global ("__sdabase", ofs, &cache, &warn_sda);
212 }
213 
214 static bfd_reloc_status_type
mep_final_link_relocate(reloc_howto_type * howto,bfd * input_bfd,asection * input_section,bfd_byte * contents,Elf_Internal_Rela * rel,bfd_vma relocation)215 mep_final_link_relocate
216     (reloc_howto_type *	 howto,
217      bfd *		 input_bfd,
218      asection *		 input_section,
219      bfd_byte *		 contents,
220      Elf_Internal_Rela * rel,
221      bfd_vma		 relocation)
222 {
223   unsigned long u;
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   u = relocation + rel->r_addend;
245 
246   byte = (unsigned char *)contents + rel->r_offset;
247 
248   if (howto->type == R_MEP_PCREL24A2
249       && u == 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     u -= pc;
260 
261   switch (howto->type)
262     {
263     /* MEPRELOC:APPLY */
264     /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
265     case R_MEP_8: /* 76543210 */
266       if (u > 255) r = bfd_reloc_overflow;
267       byte[0] = (u & 0xff);
268       break;
269     case R_MEP_16: /* fedcba9876543210 */
270       if (u > 65535) r = bfd_reloc_overflow;
271       byte[0^e2] = ((u >> 8) & 0xff);
272       byte[1^e2] = (u & 0xff);
273       break;
274     case R_MEP_32: /* vutsrqponmlkjihgfedcba9876543210 */
275       byte[0^e4] = ((u >> 24) & 0xff);
276       byte[1^e4] = ((u >> 16) & 0xff);
277       byte[2^e4] = ((u >> 8) & 0xff);
278       byte[3^e4] = (u & 0xff);
279       break;
280     case R_MEP_PCREL8A2: /* --------7654321- */
281       if (u + 128 > 255) r = bfd_reloc_overflow;
282       byte[1^e2] = (byte[1^e2] & 0x01) | (u & 0xfe);
283       break;
284     case R_MEP_PCREL12A2: /* ----ba987654321- */
285       if (u + 2048 > 4095) r = bfd_reloc_overflow;
286       byte[0^e2] = (byte[0^e2] & 0xf0) | ((u >> 8) & 0x0f);
287       byte[1^e2] = (byte[1^e2] & 0x01) | (u & 0xfe);
288       break;
289     case R_MEP_PCREL17A2: /* ----------------gfedcba987654321 */
290       if (u + 65536 > 131071) r = bfd_reloc_overflow;
291       byte[2^e2] = ((u >> 9) & 0xff);
292       byte[3^e2] = ((u >> 1) & 0xff);
293       break;
294     case R_MEP_PCREL24A2: /* -----7654321----nmlkjihgfedcba98 */
295       if (u + 8388608 > 16777215) r = bfd_reloc_overflow;
296       byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
297       byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
298       byte[2^e2] = ((u >> 16) & 0xff);
299       byte[3^e2] = ((u >> 8) & 0xff);
300       break;
301     case R_MEP_PCABS24A2: /* -----7654321----nmlkjihgfedcba98 */
302       if (u > 16777215) r = bfd_reloc_overflow;
303       byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
304       byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
305       byte[2^e2] = ((u >> 16) & 0xff);
306       byte[3^e2] = ((u >> 8) & 0xff);
307       break;
308     case R_MEP_LOW16: /* ----------------fedcba9876543210 */
309       byte[2^e2] = ((u >> 8) & 0xff);
310       byte[3^e2] = (u & 0xff);
311       break;
312     case R_MEP_HI16U: /* ----------------vutsrqponmlkjihg */
313       byte[2^e2] = ((u >> 24) & 0xff);
314       byte[3^e2] = ((u >> 16) & 0xff);
315       break;
316     case R_MEP_HI16S: /* ----------------vutsrqponmlkjihg */
317       u += 0x8000;
318       byte[2^e2] = ((u >> 24) & 0xff);
319       byte[3^e2] = ((u >> 16) & 0xff);
320       break;
321     case R_MEP_GPREL: /* ----------------fedcba9876543210 */
322       u -= mep_sdaoff_base(rel->r_offset);
323       if (u + 32768 > 65535) r = bfd_reloc_overflow;
324       byte[2^e2] = ((u >> 8) & 0xff);
325       byte[3^e2] = (u & 0xff);
326       break;
327     case R_MEP_TPREL: /* ----------------fedcba9876543210 */
328       u -= mep_tpoff_base(rel->r_offset);
329       if (u + 32768 > 65535) r = bfd_reloc_overflow;
330       byte[2^e2] = ((u >> 8) & 0xff);
331       byte[3^e2] = (u & 0xff);
332       break;
333     case R_MEP_TPREL7: /* ---------6543210 */
334       u -= mep_tpoff_base(rel->r_offset);
335       if (u > 127) r = bfd_reloc_overflow;
336       byte[1^e2] = (byte[1^e2] & 0x80) | (u & 0x7f);
337       break;
338     case R_MEP_TPREL7A2: /* ---------654321- */
339       u -= mep_tpoff_base(rel->r_offset);
340       if (u > 127) r = bfd_reloc_overflow;
341       byte[1^e2] = (byte[1^e2] & 0x81) | (u & 0x7e);
342       break;
343     case R_MEP_TPREL7A4: /* ---------65432-- */
344       u -= mep_tpoff_base(rel->r_offset);
345       if (u > 127) r = bfd_reloc_overflow;
346       byte[1^e2] = (byte[1^e2] & 0x83) | (u & 0x7c);
347       break;
348     case R_MEP_UIMM24: /* --------76543210nmlkjihgfedcba98 */
349       if (u > 16777215) r = bfd_reloc_overflow;
350       byte[1^e2] = (u & 0xff);
351       byte[2^e2] = ((u >> 16) & 0xff);
352       byte[3^e2] = ((u >> 8) & 0xff);
353       break;
354     case R_MEP_ADDR24A4: /* --------765432--nmlkjihgfedcba98 */
355       if (u > 16777215) r = bfd_reloc_overflow;
356       byte[1^e2] = (byte[1^e2] & 0x03) | (u & 0xfc);
357       byte[2^e2] = ((u >> 16) & 0xff);
358       byte[3^e2] = ((u >> 8) & 0xff);
359       break;
360     case R_MEP_GNU_VTINHERIT: /* ---------------- */
361       break;
362     case R_MEP_GNU_VTENTRY: /* ---------------- */
363       break;
364     /* MEPRELOC:END */
365     default:
366       abort ();
367     }
368 
369   return r;
370 }
371 
372 /* Set the howto pointer for a MEP ELF reloc.  */
373 
374 static bool
mep_info_to_howto_rela(bfd * abfd,arelent * cache_ptr,Elf_Internal_Rela * dst)375 mep_info_to_howto_rela (bfd *		    abfd,
376 			arelent *	    cache_ptr,
377 			Elf_Internal_Rela * dst)
378 {
379   unsigned int r_type;
380 
381   r_type = ELF32_R_TYPE (dst->r_info);
382   if (r_type >= R_MEP_max)
383     {
384       /* xgettext:c-format */
385       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
386 			  abfd, r_type);
387       bfd_set_error (bfd_error_bad_value);
388       return false;
389     }
390   cache_ptr->howto = & mep_elf_howto_table [r_type];
391   return true;
392 }
393 
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 int
mep_elf_relocate_section(bfd * output_bfd ATTRIBUTE_UNUSED,struct bfd_link_info * info,bfd * input_bfd,asection * input_section,bfd_byte * contents,Elf_Internal_Rela * relocs,Elf_Internal_Sym * local_syms,asection ** local_sections)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 (sec) : name;
477 	}
478       else
479 	{
480 	  bool 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 
556 /* Function to set the ELF flag bits.  */
557 
558 static bool
mep_elf_set_private_flags(bfd * abfd,flagword flags)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 bool
mep_elf_merge_private_bfd_data(bfd * ibfd,struct bfd_link_info * info)571 mep_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
572 {
573   bfd *obfd = info->output_bfd;
574   static bfd *last_ibfd = 0;
575   flagword old_flags, new_flags;
576   flagword old_partial, new_partial;
577 
578   /* Check if we have the same endianness.  */
579   if (!_bfd_generic_verify_endian_match (ibfd, info))
580     return false;
581 
582   new_flags = elf_elfheader (ibfd)->e_flags;
583   old_flags = elf_elfheader (obfd)->e_flags;
584 
585 #ifdef DEBUG
586   _bfd_error_handler ("%pB: old_flags = 0x%.8x, new_flags = 0x%.8x, init = %s",
587 		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
588 #endif
589 
590     /* First call, no flags set.  */
591     if (!elf_flags_init (obfd))
592     {
593       elf_flags_init (obfd) = true;
594       old_flags = new_flags;
595     }
596   else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
597     {
598       /* Non-library flags trump library flags.  The choice doesn't really
599 	 matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
600       if (old_flags & EF_MEP_LIBRARY)
601 	old_flags = new_flags;
602     }
603   else
604     {
605       /* Make sure they're for the same mach.  Allow upgrade from the "mep"
606 	 mach.  */
607       new_partial = (new_flags & EF_MEP_CPU_MASK);
608       old_partial = (old_flags & EF_MEP_CPU_MASK);
609       if (new_partial == old_partial)
610 	;
611       else if (new_partial == EF_MEP_CPU_MEP)
612 	;
613       else if (old_partial == EF_MEP_CPU_MEP)
614 	old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
615       else
616 	{
617 	  /* xgettext:c-format */
618 	  _bfd_error_handler (_("%pB and %pB are for different cores"),
619 			      last_ibfd, ibfd);
620 	  bfd_set_error (bfd_error_invalid_target);
621 	  return false;
622 	}
623 
624       /* Make sure they're for the same me_module.  Allow basic config to
625 	 mix with any other.  */
626       new_partial = (new_flags & EF_MEP_INDEX_MASK);
627       old_partial = (old_flags & EF_MEP_INDEX_MASK);
628       if (new_partial == old_partial)
629 	;
630       else if (new_partial == 0)
631 	;
632       else if (old_partial == 0)
633 	old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
634       else
635 	{
636 	  /* xgettext:c-format */
637 	  _bfd_error_handler (_("%pB and %pB are for different configurations"),
638 			      last_ibfd, ibfd);
639 	  bfd_set_error (bfd_error_invalid_target);
640 	  return false;
641 	}
642     }
643 
644   elf_elfheader (obfd)->e_flags = old_flags;
645   last_ibfd = ibfd;
646   return true;
647 }
648 
649 /* This will be edited by the MeP configration tool.  */
650 static const char * config_names[] =
651 {
652   "basic"
653   /* start-mepcfgtool */
654   ,"default"
655   /* end-mepcfgtool */
656 };
657 
658 static const char * core_names[] =
659 {
660   "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
661 };
662 
663 static bool
mep_elf_print_private_bfd_data(bfd * abfd,void * ptr)664 mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
665 {
666   FILE *   file = (FILE *) ptr;
667   flagword flags, partial_flags;
668 
669   BFD_ASSERT (abfd != NULL && ptr != NULL);
670 
671   /* Print normal ELF private data.  */
672   _bfd_elf_print_private_bfd_data (abfd, ptr);
673 
674   flags = elf_elfheader (abfd)->e_flags;
675   fprintf (file, _("private flags = 0x%lx"), (unsigned long) flags);
676 
677   partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
678   if (partial_flags < ARRAY_SIZE (core_names))
679     fprintf (file, "  core: %s", core_names[(long)partial_flags]);
680 
681   partial_flags = flags & EF_MEP_INDEX_MASK;
682   if (partial_flags < ARRAY_SIZE (config_names))
683     fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);
684 
685   fputc ('\n', file);
686 
687   return true;
688 }
689 
690 /* Return the machine subcode from the ELF e_flags header.  */
691 
692 static int
elf32_mep_machine(bfd * abfd)693 elf32_mep_machine (bfd * abfd)
694 {
695   switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
696     {
697     default: break;
698     case EF_MEP_CPU_C2: return bfd_mach_mep;
699     case EF_MEP_CPU_C3: return bfd_mach_mep;
700     case EF_MEP_CPU_C4: return bfd_mach_mep;
701     case EF_MEP_CPU_C5: return bfd_mach_mep_c5;
702     case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
703     }
704 
705   return bfd_mach_mep;
706 }
707 
708 static bool
mep_elf_object_p(bfd * abfd)709 mep_elf_object_p (bfd * abfd)
710 {
711   bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
712   return true;
713 }
714 
715 static bool
mep_elf_section_flags(const Elf_Internal_Shdr * hdr)716 mep_elf_section_flags (const Elf_Internal_Shdr *hdr)
717 {
718   if (hdr->sh_flags & SHF_MEP_VLIW)
719     hdr->bfd_section->flags |= SEC_MEP_VLIW;
720   return true;
721 }
722 
723 static bool
mep_elf_fake_sections(bfd * abfd ATTRIBUTE_UNUSED,Elf_Internal_Shdr * hdr,asection * sec)724 mep_elf_fake_sections (bfd *		   abfd ATTRIBUTE_UNUSED,
725 		       Elf_Internal_Shdr * hdr,
726 		       asection *	   sec)
727 {
728   if (sec->flags & SEC_MEP_VLIW)
729     hdr->sh_flags |= SHF_MEP_VLIW;
730   return true;
731 }
732 
733 
734 #define ELF_ARCH		bfd_arch_mep
735 #define ELF_MACHINE_CODE	EM_CYGNUS_MEP
736 #define ELF_MAXPAGESIZE		0x1000
737 
738 #define TARGET_BIG_SYM		mep_elf32_vec
739 #define TARGET_BIG_NAME		"elf32-mep"
740 
741 #define TARGET_LITTLE_SYM	mep_elf32_le_vec
742 #define TARGET_LITTLE_NAME	"elf32-mep-little"
743 
744 #define elf_info_to_howto_rel			NULL
745 #define elf_info_to_howto			mep_info_to_howto_rela
746 #define elf_backend_relocate_section		mep_elf_relocate_section
747 #define elf_backend_object_p			mep_elf_object_p
748 #define elf_backend_section_flags		mep_elf_section_flags
749 #define elf_backend_fake_sections		mep_elf_fake_sections
750 
751 #define bfd_elf32_bfd_reloc_type_lookup		mep_reloc_type_lookup
752 #define bfd_elf32_bfd_reloc_name_lookup		mep_reloc_name_lookup
753 #define bfd_elf32_bfd_set_private_flags		mep_elf_set_private_flags
754 #define bfd_elf32_bfd_merge_private_bfd_data	mep_elf_merge_private_bfd_data
755 #define bfd_elf32_bfd_print_private_bfd_data	mep_elf_print_private_bfd_data
756 
757 #define elf_backend_rela_normal			1
758 
759 #include "elf32-target.h"
760