bfd/
[deliverable/binutils-gdb.git] / bfd / elf32-mep.c
CommitLineData
d9352518 1/* MeP-specific support for 32-bit ELF.
4a97a0e5 2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
dbaa2011 3 2010, 2011, 2012 Free Software Foundation, Inc.
d9352518
DB
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
cd123cb7 9 the Free Software Foundation; either version 3 of the License, or
d9352518
DB
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
cd123cb7
NC
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 MA 02110-1301, USA. */
d9352518 21
d9352518 22#include "sysdep.h"
3db64b00 23#include "bfd.h"
d9352518
DB
24#include "libbfd.h"
25#include "elf-bfd.h"
26#include "elf/mep.h"
27#include "libiberty.h"
28
29/* Forward declarations. */
30
31/* Private relocation functions. */
32\f
33#define MEPREL(type, size, bits, right, left, pcrel, overflow, mask) \
34 {(unsigned)type, right, size, bits, pcrel, left, overflow, mep_reloc, #type, FALSE, 0, mask, 0 }
35
36#define N complain_overflow_dont
37#define S complain_overflow_signed
38#define U complain_overflow_unsigned
39
40static bfd_reloc_status_type mep_reloc (bfd *, arelent *, struct bfd_symbol *,
41 void *, asection *, bfd *, char **);
42
43static 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
80static bfd_reloc_status_type
81mep_reloc
82 (bfd * abfd ATTRIBUTE_UNUSED,
83 arelent * reloc_entry ATTRIBUTE_UNUSED,
84 struct bfd_symbol * symbol ATTRIBUTE_UNUSED,
85 void * data ATTRIBUTE_UNUSED,
86 asection * input_section ATTRIBUTE_UNUSED,
87 bfd * output_bfd ATTRIBUTE_UNUSED,
88 char ** error_message ATTRIBUTE_UNUSED)
89{
90 return bfd_reloc_ok;
91}
92
93\f
94
95#define BFD_RELOC_MEP_NONE BFD_RELOC_NONE
96#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
97#define MAP(n) case BFD_RELOC_MEP_##n: type = R_MEP_##n; break
98#else
99#define MAP(n) case BFD_RELOC_MEP_/**/n: type = R_MEP_/**/n; break
100#endif
101
102static reloc_howto_type *
103mep_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. */
4a97a0e5 157 (*_bfd_error_handler) (_("mep: no reloc for code %d"), code);
d9352518
DB
158 return NULL;
159 }
160
161 if (mep_elf_howto_table[type].type != type)
162 {
4a97a0e5
AM
163 (*_bfd_error_handler) (_("MeP: howto %d has type %d"),
164 type, mep_elf_howto_table[type].type);
d9352518
DB
165 abort ();
166 }
167
168 return mep_elf_howto_table + type;
169}
170
171#undef MAP
172
157090f7
AM
173static reloc_howto_type *
174mep_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}
d9352518
DB
187\f
188/* Perform a single relocation. */
189
190static struct bfd_link_info *mep_info;
191static int warn_tp = 0, warn_sda = 0;
192
193static bfd_vma
194mep_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
217static bfd_vma
218mep_tpoff_base (bfd_vma ofs)
219{
220 static bfd_vma cache = 0;
221 return mep_lookup_global ("__tpbase", ofs, &cache, &warn_tp);
222}
223
224static bfd_vma
225mep_sdaoff_base (bfd_vma ofs)
226{
227 static bfd_vma cache = 0;
228 return mep_lookup_global ("__sdabase", ofs, &cache, &warn_sda);
229}
230
231static bfd_reloc_status_type
232mep_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 */
b4928193
NC
337 if (s & 0x8000)
338 s += 0x10000;
d9352518
DB
339 byte[2^e2] = ((s >> 24) & 0xff);
340 byte[3^e2] = ((s >> 16) & 0xff);
341 break;
342 case R_MEP_GPREL: /* ----------------fedcba9876543210 */
343 s -= mep_sdaoff_base(rel->r_offset);
344 if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
345 byte[2^e2] = ((s >> 8) & 0xff);
346 byte[3^e2] = (s & 0xff);
347 break;
348 case R_MEP_TPREL: /* ----------------fedcba9876543210 */
349 s -= mep_tpoff_base(rel->r_offset);
350 if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
351 byte[2^e2] = ((s >> 8) & 0xff);
352 byte[3^e2] = (s & 0xff);
353 break;
354 case R_MEP_TPREL7: /* ---------6543210 */
355 u -= mep_tpoff_base(rel->r_offset);
356 if (u > 127) r = bfd_reloc_overflow;
357 byte[1^e2] = (byte[1^e2] & 0x80) | (u & 0x7f);
358 break;
359 case R_MEP_TPREL7A2: /* ---------654321- */
360 u -= mep_tpoff_base(rel->r_offset);
361 if (u > 127) r = bfd_reloc_overflow;
362 byte[1^e2] = (byte[1^e2] & 0x81) | (u & 0x7e);
363 break;
364 case R_MEP_TPREL7A4: /* ---------65432-- */
365 u -= mep_tpoff_base(rel->r_offset);
366 if (u > 127) r = bfd_reloc_overflow;
367 byte[1^e2] = (byte[1^e2] & 0x83) | (u & 0x7c);
368 break;
369 case R_MEP_UIMM24: /* --------76543210nmlkjihgfedcba98 */
370 if (u > 16777215) r = bfd_reloc_overflow;
371 byte[1^e2] = (u & 0xff);
372 byte[2^e2] = ((u >> 16) & 0xff);
373 byte[3^e2] = ((u >> 8) & 0xff);
374 break;
375 case R_MEP_ADDR24A4: /* --------765432--nmlkjihgfedcba98 */
376 if (u > 16777215) r = bfd_reloc_overflow;
377 byte[1^e2] = (byte[1^e2] & 0x03) | (u & 0xfc);
378 byte[2^e2] = ((u >> 16) & 0xff);
379 byte[3^e2] = ((u >> 8) & 0xff);
380 break;
381 case R_MEP_GNU_VTINHERIT: /* ---------------- */
382 break;
383 case R_MEP_GNU_VTENTRY: /* ---------------- */
384 break;
385 /* MEPRELOC:END */
386 default:
387 abort ();
388 }
389
390 return r;
391}
392\f
393/* Set the howto pointer for a MEP ELF reloc. */
394
395static void
396mep_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}
d9352518
DB
406\f
407/* Relocate a MEP ELF section.
408 There is some attempt to make this function usable for many architectures,
409 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
410 if only to serve as a learning tool.
411
412 The RELOCATE_SECTION function is called by the new ELF backend linker
413 to handle the relocations for a section.
414
415 The relocs are always passed as Rela structures; if the section
416 actually uses Rel structures, the r_addend field will always be
417 zero.
418
419 This function is responsible for adjusting the section contents as
420 necessary, and (if using Rela relocs and generating a relocatable
421 output file) adjusting the reloc addend as necessary.
422
423 This function does not have to worry about setting the reloc
424 address or the reloc symbol index.
425
426 LOCAL_SYMS is a pointer to the swapped in local symbols.
427
428 LOCAL_SECTIONS is an array giving the section in the input file
429 corresponding to the st_shndx field of each local symbol.
430
431 The global hash table entry for the global symbols can be found
432 via elf_sym_hashes (input_bfd).
433
434 When generating relocatable output, this function must handle
435 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
436 going to be the section symbol corresponding to the output
437 section, which means that the addend must be adjusted
438 accordingly. */
439
440static bfd_boolean
441mep_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);
d9352518 475 r_symndx = ELF32_R_SYM (rel->r_info);
d9352518
DB
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;
d9352518
DB
490 }
491 else
492 {
0f02bbd9 493 bfd_boolean warned, unresolved_reloc;
d9352518 494
0f02bbd9
AM
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);
d9352518
DB
499
500 name = h->root.root.string;
d9352518
DB
501 }
502
dbaa2011 503 if (sec != NULL && discarded_section (sec))
e4067dbb 504 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
545fd46b 505 rel, 1, relend, howto, 0, contents);
ab96bf03
AM
506
507 if (info->relocatable)
0f02bbd9 508 continue;
ab96bf03 509
cdfeee4f
AM
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);
d9352518
DB
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}
d9352518
DB
571\f
572/* Function to set the ELF flag bits. */
573
574static bfd_boolean
575mep_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
583static bfd_boolean
584mep_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;
104d59d1
JM
592
593 /* Copy object attributes. */
594 _bfd_elf_copy_obj_attributes (ibfd, obfd);
595
d9352518
DB
596 return TRUE;
597}
598
599/* Merge backend specific data from an object file to the output
600 object file when linking. */
601
602static bfd_boolean
603mep_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
cc643b88 609 /* Check if we have the same endianness. */
d9352518
DB
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. */
677static const char * config_names[] =
678{
679 "basic"
680 /* start-mepcfgtool */
c1a0a41f 681 ,"default"
d9352518
DB
682 /* end-mepcfgtool */
683};
684
685static const char * core_names[] =
686{
687 "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
688};
689
690static bfd_boolean
691mep_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;
0af1713e 702 fprintf (file, _("private flags = 0x%lx"), (unsigned long) flags);
d9352518
DB
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
719static int
720elf32_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;
4d28413b 728 case EF_MEP_CPU_C5: return bfd_mach_mep_c5;
d9352518
DB
729 case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
730 }
731
732 return bfd_mach_mep;
733}
734
735static bfd_boolean
736mep_elf_object_p (bfd * abfd)
737{
d9352518
DB
738 bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
739 return TRUE;
740}
741
742static bfd_boolean
743mep_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
750static bfd_boolean
751mep_elf_fake_sections (bfd * abfd ATTRIBUTE_UNUSED,
752 Elf_Internal_Shdr * hdr,
753 asection * sec)
754{
755 if (sec->flags & SEC_MEP_VLIW)
756 hdr->sh_flags |= SHF_MEP_VLIW;
757 return TRUE;
758}
759
760\f
761#define ELF_ARCH bfd_arch_mep
762#define ELF_MACHINE_CODE EM_CYGNUS_MEP
763#define ELF_MAXPAGESIZE 0x1000
764
765#define TARGET_BIG_SYM bfd_elf32_mep_vec
766#define TARGET_BIG_NAME "elf32-mep"
767
768#define TARGET_LITTLE_SYM bfd_elf32_mep_little_vec
769#define TARGET_LITTLE_NAME "elf32-mep-little"
770
771#define elf_info_to_howto_rel NULL
772#define elf_info_to_howto mep_info_to_howto_rela
773#define elf_backend_relocate_section mep_elf_relocate_section
d9352518
DB
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
d9352518 778#define bfd_elf32_bfd_reloc_type_lookup mep_reloc_type_lookup
0f02bbd9 779#define bfd_elf32_bfd_reloc_name_lookup mep_reloc_name_lookup
d9352518
DB
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
0f02bbd9 785#define elf_backend_rela_normal 1
d9352518
DB
786
787#include "elf32-target.h"
This page took 0.298322 seconds and 4 git commands to generate.