Coverage Report

Created: 2026-03-10 08:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/binutils-gdb/bfd/elf32-mep.c
Line
Count
Source
1
/* MeP-specific support for 32-bit ELF.
2
   Copyright (C) 2001-2026 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,   0,  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,        1,  8, 0, 0, 0, U, 0xff),
47
  MEPREL (R_MEP_16,       2, 16, 0, 0, 0, U, 0xffff),
48
  MEPREL (R_MEP_32,       4, 32, 0, 0, 0, U, 0xffffffff),
49
  MEPREL (R_MEP_PCREL8A2, 2,  8, 1, 1, 1, S, 0x00fe),
50
  MEPREL (R_MEP_PCREL12A2,2, 12, 1, 1, 1, S, 0x0ffe),
51
  MEPREL (R_MEP_PCREL17A2,4, 17, 0, 1, 1, S, 0x0000ffff),
52
  MEPREL (R_MEP_PCREL24A2,4, 24, 0, 1, 1, S, 0x07f0ffff),
53
  MEPREL (R_MEP_PCABS24A2,4, 24, 0, 1, 0, U, 0x07f0ffff),
54
  MEPREL (R_MEP_LOW16,    4, 16, 0, 0, 0, N, 0x0000ffff),
55
  MEPREL (R_MEP_HI16U,    4, 32, 0,16, 0, N, 0x0000ffff),
56
  MEPREL (R_MEP_HI16S,    4, 32, 0,16, 0, N, 0x0000ffff),
57
  MEPREL (R_MEP_GPREL,    4, 16, 0, 0, 0, S, 0x0000ffff),
58
  MEPREL (R_MEP_TPREL,    4, 16, 0, 0, 0, S, 0x0000ffff),
59
  MEPREL (R_MEP_TPREL7,   2,  7, 0, 0, 0, U, 0x007f),
60
  MEPREL (R_MEP_TPREL7A2, 2,  7, 1, 1, 0, U, 0x007e),
61
  MEPREL (R_MEP_TPREL7A4, 2,  7, 2, 2, 0, U, 0x007c),
62
  MEPREL (R_MEP_UIMM24,   4, 24, 0, 0, 0, U, 0x00ffffff),
63
  MEPREL (R_MEP_ADDR24A4, 4, 24, 0, 2, 0, U, 0x00fcffff),
64
  MEPREL (R_MEP_GNU_VTINHERIT,2,  0,16,32, 0, N, 0x0000),
65
  MEPREL (R_MEP_GNU_VTENTRY,2,  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
0
#define BFD_RELOC_MEP_NONE BFD_RELOC_NONE
78
#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
79
0
#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 *
85
mep_reloc_type_lookup
86
    (bfd * abfd ATTRIBUTE_UNUSED,
87
     bfd_reloc_code_real_type code)
88
0
{
89
0
  unsigned int type = 0;
90
91
0
  switch (code)
92
0
    {
93
0
    MAP(NONE);
94
0
    case BFD_RELOC_8:
95
0
      type = R_MEP_8;
96
0
      break;
97
0
    case BFD_RELOC_16:
98
0
      type = R_MEP_16;
99
0
      break;
100
0
    case BFD_RELOC_32:
101
0
      type = R_MEP_32;
102
0
      break;
103
0
    case BFD_RELOC_VTABLE_ENTRY:
104
0
      type = R_MEP_GNU_VTENTRY;
105
0
      break;
106
0
    case BFD_RELOC_VTABLE_INHERIT:
107
0
      type = R_MEP_GNU_VTINHERIT;
108
0
      break;
109
0
    case BFD_RELOC_RELC:
110
0
      type = R_RELC;
111
0
      break;
112
113
    /* MEPRELOC:MAP */
114
    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
115
0
    MAP(8);
116
0
    MAP(16);
117
0
    MAP(32);
118
0
    MAP(PCREL8A2);
119
0
    MAP(PCREL12A2);
120
0
    MAP(PCREL17A2);
121
0
    MAP(PCREL24A2);
122
0
    MAP(PCABS24A2);
123
0
    MAP(LOW16);
124
0
    MAP(HI16U);
125
0
    MAP(HI16S);
126
0
    MAP(GPREL);
127
0
    MAP(TPREL);
128
0
    MAP(TPREL7);
129
0
    MAP(TPREL7A2);
130
0
    MAP(TPREL7A4);
131
0
    MAP(UIMM24);
132
0
    MAP(ADDR24A4);
133
0
    MAP(GNU_VTINHERIT);
134
0
    MAP(GNU_VTENTRY);
135
    /* MEPRELOC:END */
136
137
0
    default:
138
      /* Pacify gcc -Wall.  */
139
0
      _bfd_error_handler (_("mep: no reloc for code %d"), code);
140
0
      return NULL;
141
0
    }
142
143
0
  if (mep_elf_howto_table[type].type != type)
144
0
    {
145
      /* xgettext:c-format */
146
0
      _bfd_error_handler (_("MeP: howto %d has type %d"),
147
0
        type, mep_elf_howto_table[type].type);
148
0
      abort ();
149
0
    }
150
151
0
  return mep_elf_howto_table + type;
152
0
}
153
154
#undef MAP
155
156
static reloc_howto_type *
157
mep_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
158
0
{
159
0
  unsigned int i;
160
161
0
  for (i = 0;
162
0
       i < sizeof (mep_elf_howto_table) / sizeof (mep_elf_howto_table[0]);
163
0
       i++)
164
0
    if (mep_elf_howto_table[i].name != NULL
165
0
  && strcasecmp (mep_elf_howto_table[i].name, r_name) == 0)
166
0
      return &mep_elf_howto_table[i];
167
168
0
  return NULL;
169
0
}
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
177
mep_lookup_global
178
    (char *    name,
179
     bfd_vma   ofs,
180
     bfd_vma * cache,
181
     int *     warn)
182
0
{
183
0
  struct bfd_link_hash_entry *h;
184
185
0
  if (*cache || *warn)
186
0
    return *cache;
187
188
0
  h = bfd_link_hash_lookup (mep_info->hash, name, false, false, true);
189
0
  if (h == 0 || h->type != bfd_link_hash_defined)
190
0
    {
191
0
      *warn = ofs + 1;
192
0
      return 0;
193
0
    }
194
0
  *cache = (h->u.def.value
195
0
    + h->u.def.section->output_section->vma
196
0
    + h->u.def.section->output_offset);
197
0
  return *cache;
198
0
}
199
200
static bfd_vma
201
mep_tpoff_base (bfd_vma ofs)
202
0
{
203
0
  static bfd_vma cache = 0;
204
0
  return mep_lookup_global ("__tpbase", ofs, &cache, &warn_tp);
205
0
}
206
207
static bfd_vma
208
mep_sdaoff_base (bfd_vma ofs)
209
0
{
210
0
  static bfd_vma cache = 0;
211
0
  return mep_lookup_global ("__sdabase", ofs, &cache, &warn_sda);
212
0
}
213
214
static bfd_reloc_status_type
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
0
{
223
0
  unsigned long u;
224
0
  unsigned char *byte;
225
0
  bfd_vma pc;
226
0
  bfd_reloc_status_type r = bfd_reloc_ok;
227
0
  int e2, e4;
228
229
0
  if (bfd_big_endian (input_bfd))
230
0
    {
231
0
      e2 = 0;
232
0
      e4 = 0;
233
0
    }
234
0
  else
235
0
    {
236
0
      e2 = 1;
237
0
      e4 = 3;
238
0
    }
239
240
0
  pc = (input_section->output_section->vma
241
0
  + input_section->output_offset
242
0
  + rel->r_offset);
243
244
0
  u = relocation + rel->r_addend;
245
246
0
  byte = (unsigned char *)contents + rel->r_offset;
247
248
0
  if (howto->type == R_MEP_PCREL24A2
249
0
      && u == 0
250
0
      && pc >= 0x800000)
251
0
    {
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
0
      return bfd_reloc_ok;
256
0
    }
257
258
0
  if (howto->pc_relative)
259
0
    u -= pc;
260
261
0
  switch (howto->type)
262
0
    {
263
    /* MEPRELOC:APPLY */
264
    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
265
0
    case R_MEP_8: /* 76543210 */
266
0
      if (u > 255) r = bfd_reloc_overflow;
267
0
      byte[0] = (u & 0xff);
268
0
      break;
269
0
    case R_MEP_16: /* fedcba9876543210 */
270
0
      if (u > 65535) r = bfd_reloc_overflow;
271
0
      byte[0^e2] = ((u >> 8) & 0xff);
272
0
      byte[1^e2] = (u & 0xff);
273
0
      break;
274
0
    case R_MEP_32: /* vutsrqponmlkjihgfedcba9876543210 */
275
0
      byte[0^e4] = ((u >> 24) & 0xff);
276
0
      byte[1^e4] = ((u >> 16) & 0xff);
277
0
      byte[2^e4] = ((u >> 8) & 0xff);
278
0
      byte[3^e4] = (u & 0xff);
279
0
      break;
280
0
    case R_MEP_PCREL8A2: /* --------7654321- */
281
0
      if (u + 128 > 255) r = bfd_reloc_overflow;
282
0
      byte[1^e2] = (byte[1^e2] & 0x01) | (u & 0xfe);
283
0
      break;
284
0
    case R_MEP_PCREL12A2: /* ----ba987654321- */
285
0
      if (u + 2048 > 4095) r = bfd_reloc_overflow;
286
0
      byte[0^e2] = (byte[0^e2] & 0xf0) | ((u >> 8) & 0x0f);
287
0
      byte[1^e2] = (byte[1^e2] & 0x01) | (u & 0xfe);
288
0
      break;
289
0
    case R_MEP_PCREL17A2: /* ----------------gfedcba987654321 */
290
0
      if (u + 65536 > 131071) r = bfd_reloc_overflow;
291
0
      byte[2^e2] = ((u >> 9) & 0xff);
292
0
      byte[3^e2] = ((u >> 1) & 0xff);
293
0
      break;
294
0
    case R_MEP_PCREL24A2: /* -----7654321----nmlkjihgfedcba98 */
295
0
      if (u + 8388608 > 16777215) r = bfd_reloc_overflow;
296
0
      byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
297
0
      byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
298
0
      byte[2^e2] = ((u >> 16) & 0xff);
299
0
      byte[3^e2] = ((u >> 8) & 0xff);
300
0
      break;
301
0
    case R_MEP_PCABS24A2: /* -----7654321----nmlkjihgfedcba98 */
302
0
      if (u > 16777215) r = bfd_reloc_overflow;
303
0
      byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
304
0
      byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
305
0
      byte[2^e2] = ((u >> 16) & 0xff);
306
0
      byte[3^e2] = ((u >> 8) & 0xff);
307
0
      break;
308
0
    case R_MEP_LOW16: /* ----------------fedcba9876543210 */
309
0
      byte[2^e2] = ((u >> 8) & 0xff);
310
0
      byte[3^e2] = (u & 0xff);
311
0
      break;
312
0
    case R_MEP_HI16U: /* ----------------vutsrqponmlkjihg */
313
0
      byte[2^e2] = ((u >> 24) & 0xff);
314
0
      byte[3^e2] = ((u >> 16) & 0xff);
315
0
      break;
316
0
    case R_MEP_HI16S: /* ----------------vutsrqponmlkjihg */
317
0
      u += 0x8000;
318
0
      byte[2^e2] = ((u >> 24) & 0xff);
319
0
      byte[3^e2] = ((u >> 16) & 0xff);
320
0
      break;
321
0
    case R_MEP_GPREL: /* ----------------fedcba9876543210 */
322
0
      u -= mep_sdaoff_base(rel->r_offset);
323
0
      if (u + 32768 > 65535) r = bfd_reloc_overflow;
324
0
      byte[2^e2] = ((u >> 8) & 0xff);
325
0
      byte[3^e2] = (u & 0xff);
326
0
      break;
327
0
    case R_MEP_TPREL: /* ----------------fedcba9876543210 */
328
0
      u -= mep_tpoff_base(rel->r_offset);
329
0
      if (u + 32768 > 65535) r = bfd_reloc_overflow;
330
0
      byte[2^e2] = ((u >> 8) & 0xff);
331
0
      byte[3^e2] = (u & 0xff);
332
0
      break;
333
0
    case R_MEP_TPREL7: /* ---------6543210 */
334
0
      u -= mep_tpoff_base(rel->r_offset);
335
0
      if (u > 127) r = bfd_reloc_overflow;
336
0
      byte[1^e2] = (byte[1^e2] & 0x80) | (u & 0x7f);
337
0
      break;
338
0
    case R_MEP_TPREL7A2: /* ---------654321- */
339
0
      u -= mep_tpoff_base(rel->r_offset);
340
0
      if (u > 127) r = bfd_reloc_overflow;
341
0
      byte[1^e2] = (byte[1^e2] & 0x81) | (u & 0x7e);
342
0
      break;
343
0
    case R_MEP_TPREL7A4: /* ---------65432-- */
344
0
      u -= mep_tpoff_base(rel->r_offset);
345
0
      if (u > 127) r = bfd_reloc_overflow;
346
0
      byte[1^e2] = (byte[1^e2] & 0x83) | (u & 0x7c);
347
0
      break;
348
0
    case R_MEP_UIMM24: /* --------76543210nmlkjihgfedcba98 */
349
0
      if (u > 16777215) r = bfd_reloc_overflow;
350
0
      byte[1^e2] = (u & 0xff);
351
0
      byte[2^e2] = ((u >> 16) & 0xff);
352
0
      byte[3^e2] = ((u >> 8) & 0xff);
353
0
      break;
354
0
    case R_MEP_ADDR24A4: /* --------765432--nmlkjihgfedcba98 */
355
0
      if (u > 16777215) r = bfd_reloc_overflow;
356
0
      byte[1^e2] = (byte[1^e2] & 0x03) | (u & 0xfc);
357
0
      byte[2^e2] = ((u >> 16) & 0xff);
358
0
      byte[3^e2] = ((u >> 8) & 0xff);
359
0
      break;
360
0
    case R_MEP_GNU_VTINHERIT: /* ---------------- */
361
0
      break;
362
0
    case R_MEP_GNU_VTENTRY: /* ---------------- */
363
0
      break;
364
    /* MEPRELOC:END */
365
0
    default:
366
0
      abort ();
367
0
    }
368
369
0
  return r;
370
0
}
371

372
/* Set the howto pointer for a MEP ELF reloc.  */
373
374
static bool
375
mep_info_to_howto_rela (bfd *       abfd,
376
      arelent *     cache_ptr,
377
      Elf_Internal_Rela * dst)
378
0
{
379
0
  unsigned int r_type;
380
381
0
  r_type = ELF32_R_TYPE (dst->r_info);
382
0
  if (r_type >= R_MEP_max)
383
0
    {
384
      /* xgettext:c-format */
385
0
      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
386
0
        abfd, r_type);
387
0
      bfd_set_error (bfd_error_bad_value);
388
0
      return false;
389
0
    }
390
0
  cache_ptr->howto = & mep_elf_howto_table [r_type];
391
0
  return true;
392
0
}
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
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
0
{
438
0
  Elf_Internal_Shdr *   symtab_hdr;
439
0
  struct elf_link_hash_entry ** sym_hashes;
440
0
  Elf_Internal_Rela *   rel;
441
0
  Elf_Internal_Rela *   relend;
442
443
0
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
444
0
  sym_hashes = elf_sym_hashes (input_bfd);
445
0
  relend     = relocs + input_section->reloc_count;
446
447
0
  mep_info = info;
448
449
0
  for (rel = relocs; rel < relend; rel ++)
450
0
    {
451
0
      reloc_howto_type *     howto;
452
0
      unsigned long      r_symndx;
453
0
      Elf_Internal_Sym *     sym;
454
0
      asection *       sec;
455
0
      struct elf_link_hash_entry * h;
456
0
      bfd_vma        relocation;
457
0
      bfd_reloc_status_type    r;
458
0
      const char *       name = NULL;
459
0
      int        r_type;
460
461
0
      r_type = ELF32_R_TYPE (rel->r_info);
462
0
      r_symndx = ELF32_R_SYM (rel->r_info);
463
0
      howto  = mep_elf_howto_table + ELF32_R_TYPE (rel->r_info);
464
0
      h      = NULL;
465
0
      sym    = NULL;
466
0
      sec    = NULL;
467
468
0
      if (r_symndx < symtab_hdr->sh_info)
469
0
  {
470
0
    sym = local_syms + r_symndx;
471
0
    sec = local_sections [r_symndx];
472
0
    relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
473
474
0
    name = bfd_elf_string_from_elf_section
475
0
      (input_bfd, symtab_hdr->sh_link, sym->st_name);
476
0
    name = name == NULL ? bfd_section_name (sec) : name;
477
0
  }
478
0
      else
479
0
  {
480
0
    bool warned, unresolved_reloc, ignored;
481
482
0
    RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel,
483
0
          r_symndx, symtab_hdr, sym_hashes,
484
0
          h, sec, relocation,
485
0
          unresolved_reloc, warned, ignored);
486
487
0
    name = h->root.root.string;
488
0
  }
489
490
0
      if (sec != NULL && discarded_section (sec))
491
0
  RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
492
0
           rel, 1, relend, R_MEP_NONE,
493
0
           howto, 0, contents);
494
495
0
      if (bfd_link_relocatable (info))
496
0
  continue;
497
498
0
      if (r_type == R_RELC)
499
0
  r = bfd_elf_perform_complex_relocation (input_bfd, input_section,
500
0
            contents, rel, relocation);
501
0
      else
502
0
  r = mep_final_link_relocate (howto, input_bfd, input_section,
503
0
             contents, rel, relocation);
504
505
0
      if (r != bfd_reloc_ok)
506
0
  {
507
0
    const char * msg = (const char *) NULL;
508
509
0
    switch (r)
510
0
      {
511
0
      case bfd_reloc_overflow:
512
0
        (*info->callbacks->reloc_overflow)
513
0
    (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
514
0
     input_bfd, input_section, rel->r_offset);
515
0
        break;
516
517
0
      case bfd_reloc_undefined:
518
0
        (*info->callbacks->undefined_symbol)
519
0
    (info, name, input_bfd, input_section, rel->r_offset, true);
520
0
        break;
521
522
0
      case bfd_reloc_outofrange:
523
0
        msg = _("internal error: out of range error");
524
0
        break;
525
526
0
      case bfd_reloc_notsupported:
527
0
        msg = _("internal error: unsupported relocation error");
528
0
        break;
529
530
0
      case bfd_reloc_dangerous:
531
0
        msg = _("internal error: dangerous relocation");
532
0
        break;
533
534
0
      default:
535
0
        msg = _("internal error: unknown error");
536
0
        break;
537
0
      }
538
539
0
    if (msg)
540
0
      (*info->callbacks->warning) (info, msg, name, input_bfd,
541
0
           input_section, rel->r_offset);
542
0
  }
543
0
    }
544
545
0
  if (warn_tp)
546
0
    info->callbacks->undefined_symbol
547
0
      (info, "__tpbase", input_bfd, input_section, warn_tp-1, true);
548
0
  if (warn_sda)
549
0
    info->callbacks->undefined_symbol
550
0
      (info, "__sdabase", input_bfd, input_section, warn_sda-1, true);
551
0
  if (warn_sda || warn_tp)
552
0
    return false;
553
554
0
  return true;
555
0
}
556

557
/* Function to set the ELF flag bits.  */
558
559
static bool
560
mep_elf_set_private_flags (bfd *    abfd,
561
         flagword flags)
562
0
{
563
0
  elf_elfheader (abfd)->e_flags = flags;
564
0
  elf_flags_init (abfd) = true;
565
0
  return true;
566
0
}
567
568
/* Merge backend specific data from an object file to the output
569
   object file when linking.  */
570
571
static bool
572
mep_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
573
0
{
574
0
  bfd *obfd = info->output_bfd;
575
0
  static bfd *last_ibfd = 0;
576
0
  flagword old_flags, new_flags;
577
0
  flagword old_partial, new_partial;
578
579
  /* Check if we have the same endianness.  */
580
0
  if (!_bfd_generic_verify_endian_match (ibfd, info))
581
0
    return false;
582
583
0
  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
584
0
    return true;
585
586
0
  new_flags = elf_elfheader (ibfd)->e_flags;
587
0
  old_flags = elf_elfheader (obfd)->e_flags;
588
589
#ifdef DEBUG
590
  _bfd_error_handler ("%pB: old_flags = 0x%.8x, new_flags = 0x%.8x, init = %s",
591
          ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
592
#endif
593
594
    /* First call, no flags set.  */
595
0
    if (!elf_flags_init (obfd))
596
0
    {
597
0
      elf_flags_init (obfd) = true;
598
0
      old_flags = new_flags;
599
0
    }
600
0
  else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
601
0
    {
602
      /* Non-library flags trump library flags.  The choice doesn't really
603
   matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
604
0
      if (old_flags & EF_MEP_LIBRARY)
605
0
  old_flags = new_flags;
606
0
    }
607
0
  else
608
0
    {
609
      /* Make sure they're for the same mach.  Allow upgrade from the "mep"
610
   mach.  */
611
0
      new_partial = (new_flags & EF_MEP_CPU_MASK);
612
0
      old_partial = (old_flags & EF_MEP_CPU_MASK);
613
0
      if (new_partial == old_partial)
614
0
  ;
615
0
      else if (new_partial == EF_MEP_CPU_MEP)
616
0
  ;
617
0
      else if (old_partial == EF_MEP_CPU_MEP)
618
0
  old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
619
0
      else
620
0
  {
621
    /* xgettext:c-format */
622
0
    _bfd_error_handler (_("%pB and %pB are for different cores"),
623
0
            last_ibfd, ibfd);
624
0
    bfd_set_error (bfd_error_invalid_target);
625
0
    return false;
626
0
  }
627
628
      /* Make sure they're for the same me_module.  Allow basic config to
629
   mix with any other.  */
630
0
      new_partial = (new_flags & EF_MEP_INDEX_MASK);
631
0
      old_partial = (old_flags & EF_MEP_INDEX_MASK);
632
0
      if (new_partial == old_partial)
633
0
  ;
634
0
      else if (new_partial == 0)
635
0
  ;
636
0
      else if (old_partial == 0)
637
0
  old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
638
0
      else
639
0
  {
640
    /* xgettext:c-format */
641
0
    _bfd_error_handler (_("%pB and %pB are for different configurations"),
642
0
            last_ibfd, ibfd);
643
0
    bfd_set_error (bfd_error_invalid_target);
644
0
    return false;
645
0
  }
646
0
    }
647
648
0
  elf_elfheader (obfd)->e_flags = old_flags;
649
0
  last_ibfd = ibfd;
650
0
  return true;
651
0
}
652
653
/* This will be edited by the MeP configration tool.  */
654
static const char * config_names[] =
655
{
656
  "basic"
657
  /* start-mepcfgtool */
658
  ,"default"
659
  /* end-mepcfgtool */
660
};
661
662
static const char * core_names[] =
663
{
664
  "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
665
};
666
667
static bool
668
mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
669
0
{
670
0
  FILE *   file = (FILE *) ptr;
671
0
  flagword flags, partial_flags;
672
673
0
  BFD_ASSERT (abfd != NULL && ptr != NULL);
674
675
  /* Print normal ELF private data.  */
676
0
  _bfd_elf_print_private_bfd_data (abfd, ptr);
677
678
0
  flags = elf_elfheader (abfd)->e_flags;
679
0
  fprintf (file, _("private flags = 0x%lx"), (unsigned long) flags);
680
681
0
  partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
682
0
  if (partial_flags < ARRAY_SIZE (core_names))
683
0
    fprintf (file, "  core: %s", core_names[(long)partial_flags]);
684
685
0
  partial_flags = flags & EF_MEP_INDEX_MASK;
686
0
  if (partial_flags < ARRAY_SIZE (config_names))
687
0
    fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);
688
689
0
  fputc ('\n', file);
690
691
0
  return true;
692
0
}
693
694
/* Return the machine subcode from the ELF e_flags header.  */
695
696
static int
697
elf32_mep_machine (bfd * abfd)
698
0
{
699
0
  switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
700
0
    {
701
0
    default: break;
702
0
    case EF_MEP_CPU_C2: return bfd_mach_mep;
703
0
    case EF_MEP_CPU_C3: return bfd_mach_mep;
704
0
    case EF_MEP_CPU_C4: return bfd_mach_mep;
705
0
    case EF_MEP_CPU_C5: return bfd_mach_mep_c5;
706
0
    case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
707
0
    }
708
709
0
  return bfd_mach_mep;
710
0
}
711
712
static bool
713
mep_elf_object_p (bfd * abfd)
714
0
{
715
0
  bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
716
0
  return true;
717
0
}
718
719
static bool
720
mep_elf_section_flags (const Elf_Internal_Shdr *hdr)
721
0
{
722
0
  if (hdr->sh_flags & SHF_MEP_VLIW)
723
0
    hdr->bfd_section->flags |= SEC_MEP_VLIW;
724
0
  return true;
725
0
}
726
727
static bool
728
mep_elf_fake_sections (bfd *       abfd ATTRIBUTE_UNUSED,
729
           Elf_Internal_Shdr * hdr,
730
           asection *    sec)
731
0
{
732
0
  if (sec->flags & SEC_MEP_VLIW)
733
0
    hdr->sh_flags |= SHF_MEP_VLIW;
734
  return true;
735
0
}
736
737

738
#define ELF_ARCH    bfd_arch_mep
739
#define ELF_MACHINE_CODE  EM_CYGNUS_MEP
740
#define ELF_MAXPAGESIZE   0x1000
741
742
#define TARGET_BIG_SYM    mep_elf32_vec
743
#define TARGET_BIG_NAME   "elf32-mep"
744
745
#define TARGET_LITTLE_SYM mep_elf32_le_vec
746
#define TARGET_LITTLE_NAME  "elf32-mep-little"
747
748
#define elf_info_to_howto_rel     NULL
749
#define elf_info_to_howto     mep_info_to_howto_rela
750
#define elf_backend_relocate_section    mep_elf_relocate_section
751
#define elf_backend_object_p      mep_elf_object_p
752
#define elf_backend_section_flags   mep_elf_section_flags
753
#define elf_backend_fake_sections   mep_elf_fake_sections
754
755
#define bfd_elf32_bfd_reloc_type_lookup   mep_reloc_type_lookup
756
#define bfd_elf32_bfd_reloc_name_lookup   mep_reloc_name_lookup
757
#define bfd_elf32_bfd_set_private_flags   mep_elf_set_private_flags
758
#define bfd_elf32_bfd_merge_private_bfd_data  mep_elf_merge_private_bfd_data
759
#define bfd_elf32_bfd_print_private_bfd_data  mep_elf_print_private_bfd_data
760
761
#define elf_backend_rela_normal     1
762
763
#include "elf32-target.h"