*** empty log message ***
[deliverable/binutils-gdb.git] / bfd / elf32-mep.c
CommitLineData
d9352518 1/* MeP-specific support for 32-bit ELF.
ab96bf03 2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
d9352518
DB
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
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. */
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
157090f7
AM
172static reloc_howto_type *
173mep_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}
d9352518
DB
186\f
187/* Perform a single relocation. */
188
189static struct bfd_link_info *mep_info;
190static int warn_tp = 0, warn_sda = 0;
191
192static bfd_vma
193mep_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
216static bfd_vma
217mep_tpoff_base (bfd_vma ofs)
218{
219 static bfd_vma cache = 0;
220 return mep_lookup_global ("__tpbase", ofs, &cache, &warn_tp);
221}
222
223static bfd_vma
224mep_sdaoff_base (bfd_vma ofs)
225{
226 static bfd_vma cache = 0;
227 return mep_lookup_global ("__sdabase", ofs, &cache, &warn_sda);
228}
229
230static bfd_reloc_status_type
231mep_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 */
b4928193
NC
336 if (s & 0x8000)
337 s += 0x10000;
d9352518
DB
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\f
392/* Set the howto pointer for a MEP ELF reloc. */
393
394static void
395mep_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}
d9352518
DB
405\f
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
439static bfd_boolean
440mep_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);
d9352518 474 r_symndx = ELF32_R_SYM (rel->r_info);
d9352518
DB
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;
d9352518
DB
489 }
490 else
491 {
0f02bbd9 492 bfd_boolean warned, unresolved_reloc;
d9352518 493
0f02bbd9
AM
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);
d9352518
DB
498
499 name = h->root.root.string;
d9352518
DB
500 }
501
ab96bf03
AM
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)
0f02bbd9 514 continue;
ab96bf03 515
d9352518
DB
516 switch (r_type)
517 {
0f02bbd9
AM
518 case R_RELC:
519 bfd_elf_perform_complex_relocation (input_bfd, input_section,
520 contents, rel, relocation);
521 continue;
522
d9352518
DB
523 default:
524 r = mep_final_link_relocate (howto, input_bfd, input_section,
525 contents, rel, relocation);
526 break;
527 }
528
529 if (r != bfd_reloc_ok)
530 {
531 const char * msg = (const char *) NULL;
532
533 switch (r)
534 {
535 case bfd_reloc_overflow:
536 r = info->callbacks->reloc_overflow
537 (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
538 input_bfd, input_section, rel->r_offset);
539 break;
540
541 case bfd_reloc_undefined:
542 r = info->callbacks->undefined_symbol
543 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
544 break;
545
546 case bfd_reloc_outofrange:
547 msg = _("internal error: out of range error");
548 break;
549
550 case bfd_reloc_notsupported:
551 msg = _("internal error: unsupported relocation error");
552 break;
553
554 case bfd_reloc_dangerous:
555 msg = _("internal error: dangerous relocation");
556 break;
557
558 default:
559 msg = _("internal error: unknown error");
560 break;
561 }
562
563 if (msg)
564 r = info->callbacks->warning
565 (info, msg, name, input_bfd, input_section, rel->r_offset);
566
567 if (! r)
568 return FALSE;
569 }
570 }
571
572 if (warn_tp)
573 info->callbacks->undefined_symbol
574 (info, "__tpbase", input_bfd, input_section, warn_tp-1, TRUE);
575 if (warn_sda)
576 info->callbacks->undefined_symbol
577 (info, "__sdabase", input_bfd, input_section, warn_sda-1, TRUE);
578 if (warn_sda || warn_tp)
579 return FALSE;
580
581 return TRUE;
582}
d9352518
DB
583\f
584/* Function to set the ELF flag bits. */
585
586static bfd_boolean
587mep_elf_set_private_flags (bfd * abfd,
588 flagword flags)
589{
590 elf_elfheader (abfd)->e_flags = flags;
591 elf_flags_init (abfd) = TRUE;
592 return TRUE;
593}
594
595static bfd_boolean
596mep_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
597{
598 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
599 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
600 return TRUE;
601
602 elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
603 elf_flags_init (obfd) = TRUE;
104d59d1
JM
604
605 /* Copy object attributes. */
606 _bfd_elf_copy_obj_attributes (ibfd, obfd);
607
d9352518
DB
608 return TRUE;
609}
610
611/* Merge backend specific data from an object file to the output
612 object file when linking. */
613
614static bfd_boolean
615mep_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
616{
617 static bfd *last_ibfd = 0;
618 flagword old_flags, new_flags;
619 flagword old_partial, new_partial;
620
621 /* Check if we have the same endianess. */
622 if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
623 return FALSE;
624
625 new_flags = elf_elfheader (ibfd)->e_flags;
626 old_flags = elf_elfheader (obfd)->e_flags;
627
628#ifdef DEBUG
629 _bfd_error_handler ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s",
630 ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
631#endif
632
633 /* First call, no flags set. */
634 if (!elf_flags_init (obfd))
635 {
636 elf_flags_init (obfd) = TRUE;
637 old_flags = new_flags;
638 }
639 else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
640 {
641 /* Non-library flags trump library flags. The choice doesn't really
642 matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set. */
643 if (old_flags & EF_MEP_LIBRARY)
644 old_flags = new_flags;
645 }
646 else
647 {
648 /* Make sure they're for the same mach. Allow upgrade from the "mep"
649 mach. */
650 new_partial = (new_flags & EF_MEP_CPU_MASK);
651 old_partial = (old_flags & EF_MEP_CPU_MASK);
652 if (new_partial == old_partial)
653 ;
654 else if (new_partial == EF_MEP_CPU_MEP)
655 ;
656 else if (old_partial == EF_MEP_CPU_MEP)
657 old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
658 else
659 {
660 _bfd_error_handler (_("%B and %B are for different cores"), last_ibfd, ibfd);
661 bfd_set_error (bfd_error_invalid_target);
662 return FALSE;
663 }
664
665 /* Make sure they're for the same me_module. Allow basic config to
666 mix with any other. */
667 new_partial = (new_flags & EF_MEP_INDEX_MASK);
668 old_partial = (old_flags & EF_MEP_INDEX_MASK);
669 if (new_partial == old_partial)
670 ;
671 else if (new_partial == 0)
672 ;
673 else if (old_partial == 0)
674 old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
675 else
676 {
677 _bfd_error_handler (_("%B and %B are for different configurations"), last_ibfd, ibfd);
678 bfd_set_error (bfd_error_invalid_target);
679 return FALSE;
680 }
681 }
682
683 elf_elfheader (obfd)->e_flags = old_flags;
684 last_ibfd = ibfd;
685 return TRUE;
686}
687
688/* This will be edited by the MeP configration tool. */
689static const char * config_names[] =
690{
691 "basic"
692 /* start-mepcfgtool */
693 ,"simple"
694 ,"fmax"
695 /* end-mepcfgtool */
696};
697
698static const char * core_names[] =
699{
700 "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
701};
702
703static bfd_boolean
704mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
705{
706 FILE * file = (FILE *) ptr;
707 flagword flags, partial_flags;
708
709 BFD_ASSERT (abfd != NULL && ptr != NULL);
710
711 /* Print normal ELF private data. */
712 _bfd_elf_print_private_bfd_data (abfd, ptr);
713
714 flags = elf_elfheader (abfd)->e_flags;
715 fprintf (file, _("private flags = 0x%lx"), (long)flags);
716
717 partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
718 if (partial_flags < ARRAY_SIZE (core_names))
719 fprintf (file, " core: %s", core_names[(long)partial_flags]);
720
721 partial_flags = flags & EF_MEP_INDEX_MASK;
722 if (partial_flags < ARRAY_SIZE (config_names))
723 fprintf (file, " me_module: %s", config_names[(long)partial_flags]);
724
725 fputc ('\n', file);
726
727 return TRUE;
728}
729
730/* Return the machine subcode from the ELF e_flags header. */
731
732static int
733elf32_mep_machine (bfd * abfd)
734{
735 switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
736 {
737 default: break;
738 case EF_MEP_CPU_C2: return bfd_mach_mep;
739 case EF_MEP_CPU_C3: return bfd_mach_mep;
740 case EF_MEP_CPU_C4: return bfd_mach_mep;
741 case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
742 }
743
744 return bfd_mach_mep;
745}
746
747static bfd_boolean
748mep_elf_object_p (bfd * abfd)
749{
d9352518
DB
750 bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
751 return TRUE;
752}
753
754static bfd_boolean
755mep_elf_section_flags (flagword * flags, const Elf_Internal_Shdr * hdr)
756{
757 if (hdr->sh_flags & SHF_MEP_VLIW)
758 * flags |= SEC_MEP_VLIW;
759 return TRUE;
760}
761
762static bfd_boolean
763mep_elf_fake_sections (bfd * abfd ATTRIBUTE_UNUSED,
764 Elf_Internal_Shdr * hdr,
765 asection * sec)
766{
767 if (sec->flags & SEC_MEP_VLIW)
768 hdr->sh_flags |= SHF_MEP_VLIW;
769 return TRUE;
770}
771
772\f
773#define ELF_ARCH bfd_arch_mep
774#define ELF_MACHINE_CODE EM_CYGNUS_MEP
775#define ELF_MAXPAGESIZE 0x1000
776
777#define TARGET_BIG_SYM bfd_elf32_mep_vec
778#define TARGET_BIG_NAME "elf32-mep"
779
780#define TARGET_LITTLE_SYM bfd_elf32_mep_little_vec
781#define TARGET_LITTLE_NAME "elf32-mep-little"
782
783#define elf_info_to_howto_rel NULL
784#define elf_info_to_howto mep_info_to_howto_rela
785#define elf_backend_relocate_section mep_elf_relocate_section
d9352518
DB
786#define elf_backend_object_p mep_elf_object_p
787#define elf_backend_section_flags mep_elf_section_flags
788#define elf_backend_fake_sections mep_elf_fake_sections
789
d9352518 790#define bfd_elf32_bfd_reloc_type_lookup mep_reloc_type_lookup
0f02bbd9 791#define bfd_elf32_bfd_reloc_name_lookup mep_reloc_name_lookup
d9352518
DB
792#define bfd_elf32_bfd_set_private_flags mep_elf_set_private_flags
793#define bfd_elf32_bfd_copy_private_bfd_data mep_elf_copy_private_bfd_data
794#define bfd_elf32_bfd_merge_private_bfd_data mep_elf_merge_private_bfd_data
795#define bfd_elf32_bfd_print_private_bfd_data mep_elf_print_private_bfd_data
796
0f02bbd9 797#define elf_backend_rela_normal 1
d9352518
DB
798
799#include "elf32-target.h"
This page took 0.081938 seconds and 4 git commands to generate.