Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/bfd/elf32-mep.c
Line
Count
Source (jump to first uncovered line)
1
/* MeP-specific support for 32-bit ELF.
2
   Copyright (C) 2001-2025 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, howto, 0, contents);
493
494
0
      if (bfd_link_relocatable (info))
495
0
  continue;
496
497
0
      if (r_type == R_RELC)
498
0
  r = bfd_elf_perform_complex_relocation (input_bfd, input_section,
499
0
            contents, rel, relocation);
500
0
      else
501
0
  r = mep_final_link_relocate (howto, input_bfd, input_section,
502
0
             contents, rel, relocation);
503
504
0
      if (r != bfd_reloc_ok)
505
0
  {
506
0
    const char * msg = (const char *) NULL;
507
508
0
    switch (r)
509
0
      {
510
0
      case bfd_reloc_overflow:
511
0
        (*info->callbacks->reloc_overflow)
512
0
    (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
513
0
     input_bfd, input_section, rel->r_offset);
514
0
        break;
515
516
0
      case bfd_reloc_undefined:
517
0
        (*info->callbacks->undefined_symbol)
518
0
    (info, name, input_bfd, input_section, rel->r_offset, true);
519
0
        break;
520
521
0
      case bfd_reloc_outofrange:
522
0
        msg = _("internal error: out of range error");
523
0
        break;
524
525
0
      case bfd_reloc_notsupported:
526
0
        msg = _("internal error: unsupported relocation error");
527
0
        break;
528
529
0
      case bfd_reloc_dangerous:
530
0
        msg = _("internal error: dangerous relocation");
531
0
        break;
532
533
0
      default:
534
0
        msg = _("internal error: unknown error");
535
0
        break;
536
0
      }
537
538
0
    if (msg)
539
0
      (*info->callbacks->warning) (info, msg, name, input_bfd,
540
0
           input_section, rel->r_offset);
541
0
  }
542
0
    }
543
544
0
  if (warn_tp)
545
0
    info->callbacks->undefined_symbol
546
0
      (info, "__tpbase", input_bfd, input_section, warn_tp-1, true);
547
0
  if (warn_sda)
548
0
    info->callbacks->undefined_symbol
549
0
      (info, "__sdabase", input_bfd, input_section, warn_sda-1, true);
550
0
  if (warn_sda || warn_tp)
551
0
    return false;
552
553
0
  return true;
554
0
}
555

556
/* Function to set the ELF flag bits.  */
557
558
static bool
559
mep_elf_set_private_flags (bfd *    abfd,
560
         flagword flags)
561
0
{
562
0
  elf_elfheader (abfd)->e_flags = flags;
563
0
  elf_flags_init (abfd) = true;
564
0
  return true;
565
0
}
566
567
/* Merge backend specific data from an object file to the output
568
   object file when linking.  */
569
570
static bool
571
mep_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
572
0
{
573
0
  bfd *obfd = info->output_bfd;
574
0
  static bfd *last_ibfd = 0;
575
0
  flagword old_flags, new_flags;
576
0
  flagword old_partial, new_partial;
577
578
  /* Check if we have the same endianness.  */
579
0
  if (!_bfd_generic_verify_endian_match (ibfd, info))
580
0
    return false;
581
582
0
  new_flags = elf_elfheader (ibfd)->e_flags;
583
0
  old_flags = elf_elfheader (obfd)->e_flags;
584
585
#ifdef DEBUG
586
  _bfd_error_handler ("%pB: old_flags = 0x%.8x, new_flags = 0x%.8x, init = %s",
587
          ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
588
#endif
589
590
    /* First call, no flags set.  */
591
0
    if (!elf_flags_init (obfd))
592
0
    {
593
0
      elf_flags_init (obfd) = true;
594
0
      old_flags = new_flags;
595
0
    }
596
0
  else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
597
0
    {
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
0
      if (old_flags & EF_MEP_LIBRARY)
601
0
  old_flags = new_flags;
602
0
    }
603
0
  else
604
0
    {
605
      /* Make sure they're for the same mach.  Allow upgrade from the "mep"
606
   mach.  */
607
0
      new_partial = (new_flags & EF_MEP_CPU_MASK);
608
0
      old_partial = (old_flags & EF_MEP_CPU_MASK);
609
0
      if (new_partial == old_partial)
610
0
  ;
611
0
      else if (new_partial == EF_MEP_CPU_MEP)
612
0
  ;
613
0
      else if (old_partial == EF_MEP_CPU_MEP)
614
0
  old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
615
0
      else
616
0
  {
617
    /* xgettext:c-format */
618
0
    _bfd_error_handler (_("%pB and %pB are for different cores"),
619
0
            last_ibfd, ibfd);
620
0
    bfd_set_error (bfd_error_invalid_target);
621
0
    return false;
622
0
  }
623
624
      /* Make sure they're for the same me_module.  Allow basic config to
625
   mix with any other.  */
626
0
      new_partial = (new_flags & EF_MEP_INDEX_MASK);
627
0
      old_partial = (old_flags & EF_MEP_INDEX_MASK);
628
0
      if (new_partial == old_partial)
629
0
  ;
630
0
      else if (new_partial == 0)
631
0
  ;
632
0
      else if (old_partial == 0)
633
0
  old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
634
0
      else
635
0
  {
636
    /* xgettext:c-format */
637
0
    _bfd_error_handler (_("%pB and %pB are for different configurations"),
638
0
            last_ibfd, ibfd);
639
0
    bfd_set_error (bfd_error_invalid_target);
640
0
    return false;
641
0
  }
642
0
    }
643
644
0
  elf_elfheader (obfd)->e_flags = old_flags;
645
0
  last_ibfd = ibfd;
646
0
  return true;
647
0
}
648
649
/* This will be edited by the MeP configration tool.  */
650
static const char * config_names[] =
651
{
652
  "basic"
653
  /* start-mepcfgtool */
654
  ,"default"
655
  /* end-mepcfgtool */
656
};
657
658
static const char * core_names[] =
659
{
660
  "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
661
};
662
663
static bool
664
mep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
665
0
{
666
0
  FILE *   file = (FILE *) ptr;
667
0
  flagword flags, partial_flags;
668
669
0
  BFD_ASSERT (abfd != NULL && ptr != NULL);
670
671
  /* Print normal ELF private data.  */
672
0
  _bfd_elf_print_private_bfd_data (abfd, ptr);
673
674
0
  flags = elf_elfheader (abfd)->e_flags;
675
0
  fprintf (file, _("private flags = 0x%lx"), (unsigned long) flags);
676
677
0
  partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
678
0
  if (partial_flags < ARRAY_SIZE (core_names))
679
0
    fprintf (file, "  core: %s", core_names[(long)partial_flags]);
680
681
0
  partial_flags = flags & EF_MEP_INDEX_MASK;
682
0
  if (partial_flags < ARRAY_SIZE (config_names))
683
0
    fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);
684
685
0
  fputc ('\n', file);
686
687
0
  return true;
688
0
}
689
690
/* Return the machine subcode from the ELF e_flags header.  */
691
692
static int
693
elf32_mep_machine (bfd * abfd)
694
0
{
695
0
  switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
696
0
    {
697
0
    default: break;
698
0
    case EF_MEP_CPU_C2: return bfd_mach_mep;
699
0
    case EF_MEP_CPU_C3: return bfd_mach_mep;
700
0
    case EF_MEP_CPU_C4: return bfd_mach_mep;
701
0
    case EF_MEP_CPU_C5: return bfd_mach_mep_c5;
702
0
    case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
703
0
    }
704
705
0
  return bfd_mach_mep;
706
0
}
707
708
static bool
709
mep_elf_object_p (bfd * abfd)
710
0
{
711
0
  bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
712
0
  return true;
713
0
}
714
715
static bool
716
mep_elf_section_flags (const Elf_Internal_Shdr *hdr)
717
0
{
718
0
  if (hdr->sh_flags & SHF_MEP_VLIW)
719
0
    hdr->bfd_section->flags |= SEC_MEP_VLIW;
720
0
  return true;
721
0
}
722
723
static bool
724
mep_elf_fake_sections (bfd *       abfd ATTRIBUTE_UNUSED,
725
           Elf_Internal_Shdr * hdr,
726
           asection *    sec)
727
0
{
728
0
  if (sec->flags & SEC_MEP_VLIW)
729
0
    hdr->sh_flags |= SHF_MEP_VLIW;
730
0
  return true;
731
0
}
732
733

734
#define ELF_ARCH    bfd_arch_mep
735
#define ELF_MACHINE_CODE  EM_CYGNUS_MEP
736
#define ELF_MAXPAGESIZE   0x1000
737
738
#define TARGET_BIG_SYM    mep_elf32_vec
739
#define TARGET_BIG_NAME   "elf32-mep"
740
741
#define TARGET_LITTLE_SYM mep_elf32_le_vec
742
#define TARGET_LITTLE_NAME  "elf32-mep-little"
743
744
#define elf_info_to_howto_rel     NULL
745
#define elf_info_to_howto     mep_info_to_howto_rela
746
#define elf_backend_relocate_section    mep_elf_relocate_section
747
#define elf_backend_object_p      mep_elf_object_p
748
#define elf_backend_section_flags   mep_elf_section_flags
749
#define elf_backend_fake_sections   mep_elf_fake_sections
750
751
#define bfd_elf32_bfd_reloc_type_lookup   mep_reloc_type_lookup
752
#define bfd_elf32_bfd_reloc_name_lookup   mep_reloc_name_lookup
753
#define bfd_elf32_bfd_set_private_flags   mep_elf_set_private_flags
754
#define bfd_elf32_bfd_merge_private_bfd_data  mep_elf_merge_private_bfd_data
755
#define bfd_elf32_bfd_print_private_bfd_data  mep_elf_print_private_bfd_data
756
757
#define elf_backend_rela_normal     1
758
759
#include "elf32-target.h"