]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elf32-mep.c
Re: MSP430: Support relocations for subtract expressions in .uleb128 directives
[thirdparty/binutils-gdb.git] / bfd / elf32-mep.c
CommitLineData
d9352518 1/* MeP-specific support for 32-bit ELF.
b3adc24a 2 Copyright (C) 2001-2020 Free Software Foundation, Inc.
d9352518
DB
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
cd123cb7 8 the Free Software Foundation; either version 3 of the License, or
d9352518
DB
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
cd123cb7
NC
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 MA 02110-1301, USA. */
d9352518 20
d9352518 21#include "sysdep.h"
3db64b00 22#include "bfd.h"
d9352518
DB
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\f
32#define MEPREL(type, size, bits, right, left, pcrel, overflow, mask) \
487096bf 33 HOWTO (type, right, size, bits, pcrel, left, overflow, bfd_elf_generic_reloc, #type, FALSE, 0, mask, 0)
d9352518
DB
34
35#define N complain_overflow_dont
36#define S complain_overflow_signed
37#define U complain_overflow_unsigned
38
d9352518
DB
39static reloc_howto_type mep_elf_howto_table [] =
40{
41 /* type, size, bits, leftshift, rightshift, pcrel, OD/OS/OU, mask. */
07d6d2b8
AM
42 MEPREL (R_MEP_NONE, 3, 0, 0, 0, 0, N, 0),
43 MEPREL (R_RELC, 0, 0, 0, 0, 0, N, 0),
d9352518
DB
44 /* MEPRELOC:HOWTO */
45 /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h. */
1a211fc7
AM
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),
d9352518
DB
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),
1a211fc7
AM
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),
d9352518
DB
60 MEPREL (R_MEP_TPREL7A2, 1, 7, 1, 1, 0, U, 0x007e),
61 MEPREL (R_MEP_TPREL7A4, 1, 7, 2, 2, 0, U, 0x007c),
1a211fc7 62 MEPREL (R_MEP_UIMM24, 2, 24, 0, 0, 0, U, 0x00ffffff),
d9352518
DB
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),
1a211fc7 65 MEPREL (R_MEP_GNU_VTENTRY,1, 0,16,32, 0, N, 0x0000),
d9352518
DB
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
d9352518
DB
75\f
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
84static reloc_howto_type *
85mep_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. */
4eca0228 139 _bfd_error_handler (_("mep: no reloc for code %d"), code);
d9352518
DB
140 return NULL;
141 }
142
143 if (mep_elf_howto_table[type].type != type)
144 {
695344c0 145 /* xgettext:c-format */
4eca0228
AM
146 _bfd_error_handler (_("MeP: howto %d has type %d"),
147 type, mep_elf_howto_table[type].type);
d9352518
DB
148 abort ();
149 }
150
151 return mep_elf_howto_table + type;
152}
153
154#undef MAP
155
157090f7
AM
156static reloc_howto_type *
157mep_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}
d9352518
DB
170\f
171/* Perform a single relocation. */
172
173static struct bfd_link_info *mep_info;
174static int warn_tp = 0, warn_sda = 0;
175
176static bfd_vma
177mep_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
200static bfd_vma
201mep_tpoff_base (bfd_vma ofs)
202{
203 static bfd_vma cache = 0;
204 return mep_lookup_global ("__tpbase", ofs, &cache, &warn_tp);
205}
206
207static bfd_vma
208mep_sdaoff_base (bfd_vma ofs)
209{
210 static bfd_vma cache = 0;
211 return mep_lookup_global ("__sdabase", ofs, &cache, &warn_sda);
212}
213
214static bfd_reloc_status_type
215mep_final_link_relocate
07d6d2b8
AM
216 (reloc_howto_type * howto,
217 bfd * input_bfd,
218 asection * input_section,
219 bfd_byte * contents,
d9352518 220 Elf_Internal_Rela * rel,
07d6d2b8 221 bfd_vma relocation)
d9352518
DB
222{
223 unsigned long u;
d9352518
DB
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
1a211fc7 244 u = relocation + rel->r_addend;
d9352518
DB
245
246 byte = (unsigned char *)contents + rel->r_offset;
247
248 if (howto->type == R_MEP_PCREL24A2
1a211fc7 249 && u == 0
d9352518
DB
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)
1a211fc7 259 u -= pc;
d9352518
DB
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- */
1a211fc7
AM
281 if (u + 128 > 255) r = bfd_reloc_overflow;
282 byte[1^e2] = (byte[1^e2] & 0x01) | (u & 0xfe);
d9352518
DB
283 break;
284 case R_MEP_PCREL12A2: /* ----ba987654321- */
1a211fc7
AM
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);
d9352518
DB
288 break;
289 case R_MEP_PCREL17A2: /* ----------------gfedcba987654321 */
1a211fc7
AM
290 if (u + 65536 > 131071) r = bfd_reloc_overflow;
291 byte[2^e2] = ((u >> 9) & 0xff);
292 byte[3^e2] = ((u >> 1) & 0xff);
d9352518
DB
293 break;
294 case R_MEP_PCREL24A2: /* -----7654321----nmlkjihgfedcba98 */
1a211fc7
AM
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);
d9352518
DB
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 */
1a211fc7
AM
317 u += 0x8000;
318 byte[2^e2] = ((u >> 24) & 0xff);
319 byte[3^e2] = ((u >> 16) & 0xff);
d9352518
DB
320 break;
321 case R_MEP_GPREL: /* ----------------fedcba9876543210 */
1a211fc7
AM
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);
d9352518
DB
326 break;
327 case R_MEP_TPREL: /* ----------------fedcba9876543210 */
1a211fc7
AM
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);
d9352518
DB
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\f
372/* Set the howto pointer for a MEP ELF reloc. */
373
f3185997
NC
374static bfd_boolean
375mep_info_to_howto_rela (bfd * abfd,
376 arelent * cache_ptr,
377 Elf_Internal_Rela * dst)
d9352518
DB
378{
379 unsigned int r_type;
380
381 r_type = ELF32_R_TYPE (dst->r_info);
5860e3f8
NC
382 if (r_type >= R_MEP_max)
383 {
695344c0 384 /* xgettext:c-format */
0aa13fee
AM
385 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
386 abfd, r_type);
f3185997
NC
387 bfd_set_error (bfd_error_bad_value);
388 return FALSE;
5860e3f8 389 }
d9352518 390 cache_ptr->howto = & mep_elf_howto_table [r_type];
f3185997 391 return TRUE;
d9352518 392}
d9352518
DB
393\f
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
427static bfd_boolean
428mep_elf_relocate_section
07d6d2b8 429 (bfd * output_bfd ATTRIBUTE_UNUSED,
d9352518 430 struct bfd_link_info * info,
07d6d2b8
AM
431 bfd * input_bfd,
432 asection * input_section,
433 bfd_byte * contents,
d9352518 434 Elf_Internal_Rela * relocs,
07d6d2b8
AM
435 Elf_Internal_Sym * local_syms,
436 asection ** local_sections)
d9352518 437{
07d6d2b8 438 Elf_Internal_Shdr * symtab_hdr;
d9352518 439 struct elf_link_hash_entry ** sym_hashes;
07d6d2b8
AM
440 Elf_Internal_Rela * rel;
441 Elf_Internal_Rela * relend;
d9352518
DB
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 {
07d6d2b8
AM
451 reloc_howto_type * howto;
452 unsigned long r_symndx;
453 Elf_Internal_Sym * sym;
454 asection * sec;
d9352518 455 struct elf_link_hash_entry * h;
07d6d2b8
AM
456 bfd_vma relocation;
457 bfd_reloc_status_type r;
458 const char * name = NULL;
459 int r_type;
d9352518
DB
460
461 r_type = ELF32_R_TYPE (rel->r_info);
d9352518 462 r_symndx = ELF32_R_SYM (rel->r_info);
d9352518
DB
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);
fd361982 476 name = name == NULL ? bfd_section_name (sec) : name;
d9352518
DB
477 }
478 else
479 {
62d887d4 480 bfd_boolean warned, unresolved_reloc, ignored;
d9352518 481
0f02bbd9
AM
482 RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel,
483 r_symndx, symtab_hdr, sym_hashes,
484 h, sec, relocation,
62d887d4 485 unresolved_reloc, warned, ignored);
d9352518
DB
486
487 name = h->root.root.string;
d9352518
DB
488 }
489
dbaa2011 490 if (sec != NULL && discarded_section (sec))
e4067dbb 491 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
545fd46b 492 rel, 1, relend, howto, 0, contents);
ab96bf03 493
0e1862bb 494 if (bfd_link_relocatable (info))
0f02bbd9 495 continue;
ab96bf03 496
cdfeee4f
AM
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);
d9352518
DB
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:
1a72702b 511 (*info->callbacks->reloc_overflow)
d9352518
DB
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:
1a72702b 517 (*info->callbacks->undefined_symbol)
d9352518
DB
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)
1a72702b
AM
539 (*info->callbacks->warning) (info, msg, name, input_bfd,
540 input_section, rel->r_offset);
d9352518
DB
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}
d9352518
DB
555\f
556/* Function to set the ELF flag bits. */
557
558static bfd_boolean
559mep_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
d9352518
DB
567/* Merge backend specific data from an object file to the output
568 object file when linking. */
569
570static bfd_boolean
50e03d47 571mep_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
d9352518 572{
50e03d47 573 bfd *obfd = info->output_bfd;
d9352518
DB
574 static bfd *last_ibfd = 0;
575 flagword old_flags, new_flags;
576 flagword old_partial, new_partial;
577
cc643b88 578 /* Check if we have the same endianness. */
50e03d47 579 if (!_bfd_generic_verify_endian_match (ibfd, info))
d9352518
DB
580 return FALSE;
581
582 new_flags = elf_elfheader (ibfd)->e_flags;
583 old_flags = elf_elfheader (obfd)->e_flags;
584
585#ifdef DEBUG
871b3ab2 586 _bfd_error_handler ("%pB: old_flags = 0x%.8x, new_flags = 0x%.8x, init = %s",
d9352518
DB
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 {
695344c0 617 /* xgettext:c-format */
871b3ab2 618 _bfd_error_handler (_("%pB and %pB are for different cores"),
63a5468a 619 last_ibfd, ibfd);
d9352518
DB
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 {
695344c0 636 /* xgettext:c-format */
871b3ab2 637 _bfd_error_handler (_("%pB and %pB are for different configurations"),
63a5468a 638 last_ibfd, ibfd);
d9352518
DB
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. */
650static const char * config_names[] =
651{
652 "basic"
653 /* start-mepcfgtool */
c1a0a41f 654 ,"default"
d9352518
DB
655 /* end-mepcfgtool */
656};
657
658static const char * core_names[] =
659{
660 "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
661};
662
663static bfd_boolean
664mep_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;
0af1713e 675 fprintf (file, _("private flags = 0x%lx"), (unsigned long) flags);
d9352518
DB
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
692static int
693elf32_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;
4d28413b 701 case EF_MEP_CPU_C5: return bfd_mach_mep_c5;
d9352518
DB
702 case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
703 }
704
705 return bfd_mach_mep;
706}
707
708static bfd_boolean
709mep_elf_object_p (bfd * abfd)
710{
d9352518
DB
711 bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
712 return TRUE;
713}
714
715static bfd_boolean
8c803a2d 716mep_elf_section_flags (const Elf_Internal_Shdr *hdr)
d9352518
DB
717{
718 if (hdr->sh_flags & SHF_MEP_VLIW)
8c803a2d 719 hdr->bfd_section->flags |= SEC_MEP_VLIW;
d9352518
DB
720 return TRUE;
721}
722
723static bfd_boolean
07d6d2b8 724mep_elf_fake_sections (bfd * abfd ATTRIBUTE_UNUSED,
d9352518 725 Elf_Internal_Shdr * hdr,
07d6d2b8 726 asection * sec)
d9352518
DB
727{
728 if (sec->flags & SEC_MEP_VLIW)
729 hdr->sh_flags |= SHF_MEP_VLIW;
730 return TRUE;
731}
732
733\f
734#define ELF_ARCH bfd_arch_mep
735#define ELF_MACHINE_CODE EM_CYGNUS_MEP
736#define ELF_MAXPAGESIZE 0x1000
737
6d00b590 738#define TARGET_BIG_SYM mep_elf32_vec
d9352518
DB
739#define TARGET_BIG_NAME "elf32-mep"
740
6d00b590 741#define TARGET_LITTLE_SYM mep_elf32_le_vec
d9352518
DB
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
07d6d2b8 747#define elf_backend_object_p mep_elf_object_p
d9352518
DB
748#define elf_backend_section_flags mep_elf_section_flags
749#define elf_backend_fake_sections mep_elf_fake_sections
750
d9352518 751#define bfd_elf32_bfd_reloc_type_lookup mep_reloc_type_lookup
0f02bbd9 752#define bfd_elf32_bfd_reloc_name_lookup mep_reloc_name_lookup
d9352518 753#define bfd_elf32_bfd_set_private_flags mep_elf_set_private_flags
d9352518
DB
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
0f02bbd9 757#define elf_backend_rela_normal 1
d9352518
DB
758
759#include "elf32-target.h"