Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/bfd/elf32-mt.c
Line
Count
Source (jump to first uncovered line)
1
/* Morpho Technologies MT 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/mt.h"
26
27
/* Prototypes.  */
28
static reloc_howto_type * mt_reloc_type_lookup
29
  (bfd *, bfd_reloc_code_real_type);
30
31
static bool mt_info_to_howto_rela
32
  (bfd *, arelent *, Elf_Internal_Rela *);
33
34
static bfd_reloc_status_type mt_elf_relocate_hi16
35
  (bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma);
36
37
static bfd_reloc_status_type mt_final_link_relocate
38
  (reloc_howto_type *, bfd *, asection *, bfd_byte *,
39
   Elf_Internal_Rela *, bfd_vma);
40
41
static int mt_elf_relocate_section
42
  (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
43
   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
44
45
/* Relocation tables.  */
46
static reloc_howto_type mt_elf_howto_table [] =
47
{
48
  /* This reloc does nothing.  */
49
  HOWTO (R_MT_NONE,       /* type */
50
    0,        /* rightshift */
51
    0,        /* size */
52
    0,        /* bitsize */
53
    false,      /* pc_relative */
54
    0,        /* bitpos */
55
    complain_overflow_dont, /* complain_on_overflow */
56
    bfd_elf_generic_reloc,  /* special_function */
57
    "R_MT_NONE",    /* name */
58
    false,      /* partial_inplace */
59
    0 ,       /* src_mask */
60
    0,        /* dst_mask */
61
    false),     /* pcrel_offset */
62
63
  /* A 16 bit absolute relocation.  */
64
  HOWTO (R_MT_16,       /* type */
65
    0,        /* rightshift */
66
    4,        /* size */
67
    16,       /* bitsize */
68
    false,      /* pc_relative */
69
    0,        /* bitpos */
70
    complain_overflow_dont, /* complain_on_overflow */
71
    bfd_elf_generic_reloc,  /* special_function */
72
    "R_MT_16",    /* name */
73
    false,      /* partial_inplace */
74
    0 ,       /* src_mask */
75
    0xffff,     /* dst_mask */
76
    false),     /* pcrel_offset */
77
78
  /* A 32 bit absolute relocation.  */
79
  HOWTO (R_MT_32,       /* type */
80
    0,        /* rightshift */
81
    4,        /* size */
82
    32,       /* bitsize */
83
    false,      /* pc_relative */
84
    0,        /* bitpos */
85
    complain_overflow_dont, /* complain_on_overflow */
86
    bfd_elf_generic_reloc,  /* special_function */
87
    "R_MT_32",    /* name */
88
    false,      /* partial_inplace */
89
    0 ,       /* src_mask */
90
    0xffffffff,     /* dst_mask */
91
    false),     /* pcrel_offset */
92
93
  /* A 32 bit pc-relative relocation.  */
94
  HOWTO (R_MT_32_PCREL,       /* type */
95
    0,        /* rightshift */
96
    4,        /* size */
97
    32,       /* bitsize */
98
    true,       /* pc_relative */
99
    0,        /* bitpos */
100
    complain_overflow_dont, /* complain_on_overflow */
101
    bfd_elf_generic_reloc,  /* special_function */
102
    "R_MT_32_PCREL",    /* name */
103
    false,      /* partial_inplace */
104
    0 ,       /* src_mask */
105
    0xffffffff,     /* dst_mask */
106
    true),      /* pcrel_offset */
107
108
  /* A 16 bit pc-relative relocation.  */
109
  HOWTO (R_MT_PC16,       /* type */
110
    0,        /* rightshift */
111
    4,        /* size */
112
    16,       /* bitsize */
113
    true,       /* pc_relative */
114
    0,        /* bitpos */
115
    complain_overflow_signed, /* complain_on_overflow */
116
    bfd_elf_generic_reloc,  /* special_function */
117
    "R_MT_PC16",    /* name */
118
    false,      /* partial_inplace */
119
    0,        /* src_mask */
120
    0xffff,     /* dst_mask */
121
    true),      /* pcrel_offset */
122
123
  /* high 16 bits of symbol value.  */
124
  HOWTO (R_MT_HI16,      /* type */
125
   0,     /* rightshift */
126
   4,     /* size */
127
   16,      /* bitsize */
128
   false,     /* pc_relative */
129
   0,     /* bitpos */
130
   complain_overflow_dont, /* complain_on_overflow */
131
   bfd_elf_generic_reloc, /* special_function */
132
   "R_MT_HI16",      /* name */
133
   false,      /* partial_inplace */
134
   0xffff0000,    /* src_mask */
135
   0xffff0000,    /* dst_mask */
136
   false),    /* pcrel_offset */
137
138
  /* Low 16 bits of symbol value.  */
139
  HOWTO (R_MT_LO16,      /* type */
140
   0,     /* rightshift */
141
   4,     /* size */
142
   16,      /* bitsize */
143
   false,     /* pc_relative */
144
   0,     /* bitpos */
145
   complain_overflow_dont, /* complain_on_overflow */
146
   bfd_elf_generic_reloc, /* special_function */
147
   "R_MT_LO16",      /* name */
148
   false,      /* partial_inplace */
149
   0xffff,    /* src_mask */
150
   0xffff,    /* dst_mask */
151
   false),    /* pcrel_offset */
152
};
153
154
/* Map BFD reloc types to MT ELF reloc types.  */
155
156
static reloc_howto_type *
157
mt_reloc_type_lookup
158
    (bfd *          abfd ATTRIBUTE_UNUSED,
159
     bfd_reloc_code_real_type code)
160
0
{
161
  /* Note that the mt_elf_howto_table is indxed by the R_
162
     constants.  Thus, the order that the howto records appear in the
163
     table *must* match the order of the relocation types defined in
164
     include/elf/mt.h.  */
165
166
0
  switch (code)
167
0
    {
168
0
    case BFD_RELOC_NONE:
169
0
      return &mt_elf_howto_table[ (int) R_MT_NONE];
170
0
    case BFD_RELOC_16:
171
0
      return &mt_elf_howto_table[ (int) R_MT_16];
172
0
    case BFD_RELOC_32:
173
0
      return &mt_elf_howto_table[ (int) R_MT_32];
174
0
    case BFD_RELOC_32_PCREL:
175
0
      return &mt_elf_howto_table[ (int) R_MT_32_PCREL];
176
0
    case BFD_RELOC_16_PCREL:
177
0
      return &mt_elf_howto_table[ (int) R_MT_PC16];
178
0
    case BFD_RELOC_HI16:
179
0
      return &mt_elf_howto_table[ (int) R_MT_HI16];
180
0
    case BFD_RELOC_LO16:
181
0
      return &mt_elf_howto_table[ (int) R_MT_LO16];
182
183
0
    default:
184
      /* Pacify gcc -Wall.  */
185
0
      return NULL;
186
0
    }
187
0
  return NULL;
188
0
}
189
190
static reloc_howto_type *
191
mt_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
192
          const char *r_name)
193
0
{
194
0
  unsigned int i;
195
196
0
  for (i = 0;
197
0
       i < sizeof (mt_elf_howto_table) / sizeof (mt_elf_howto_table[0]);
198
0
       i++)
199
0
    if (mt_elf_howto_table[i].name != NULL
200
0
  && strcasecmp (mt_elf_howto_table[i].name, r_name) == 0)
201
0
      return &mt_elf_howto_table[i];
202
203
0
  return NULL;
204
0
}
205
206
bfd_reloc_status_type
207
mt_elf_relocate_hi16
208
    (bfd *     input_bfd,
209
     Elf_Internal_Rela * relhi,
210
     bfd_byte *    contents,
211
     bfd_vma     value)
212
0
{
213
0
  bfd_vma insn;
214
215
0
  insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
216
217
0
  value += relhi->r_addend;
218
0
  value >>= 16;
219
0
  insn = ((insn & ~0xFFFF) | value);
220
221
0
  bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
222
0
  return bfd_reloc_ok;
223
0
}
224

225
/* XXX: The following code is the result of a cut&paste.  This unfortunate
226
   practice is very widespread in the various target back-end files.  */
227
228
/* Set the howto pointer for a MT ELF reloc.  */
229
230
static bool
231
mt_info_to_howto_rela (bfd *abfd,
232
           arelent *cache_ptr,
233
           Elf_Internal_Rela *dst)
234
0
{
235
0
  unsigned int r_type;
236
237
0
  r_type = ELF32_R_TYPE (dst->r_info);
238
0
  if (r_type >= (unsigned int) R_MT_max)
239
0
    {
240
      /* xgettext:c-format */
241
0
      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
242
0
        abfd, r_type);
243
0
      bfd_set_error (bfd_error_bad_value);
244
0
      return false;
245
0
    }
246
0
  cache_ptr->howto = & mt_elf_howto_table [r_type];
247
0
  return true;
248
0
}
249
250
/* Perform a single relocation.  By default we use the standard BFD
251
   routines.  */
252
253
static bfd_reloc_status_type
254
mt_final_link_relocate
255
    (reloc_howto_type *  howto,
256
     bfd *     input_bfd,
257
     asection *    input_section,
258
     bfd_byte *    contents,
259
     Elf_Internal_Rela * rel,
260
     bfd_vma     relocation)
261
0
{
262
0
  return _bfd_final_link_relocate (howto, input_bfd, input_section,
263
0
           contents, rel->r_offset,
264
0
           relocation, rel->r_addend);
265
0
}
266
267
/* Relocate a MT ELF section.
268
   There is some attempt to make this function usable for many architectures,
269
   both USE_REL and USE_RELA ['twould be nice if such a critter existed],
270
   if only to serve as a learning tool.
271
272
   The RELOCATE_SECTION function is called by the new ELF backend linker
273
   to handle the relocations for a section.
274
275
   The relocs are always passed as Rela structures; if the section
276
   actually uses Rel structures, the r_addend field will always be
277
   zero.
278
279
   This function is responsible for adjusting the section contents as
280
   necessary, and (if using Rela relocs and generating a relocatable
281
   output file) adjusting the reloc addend as necessary.
282
283
   This function does not have to worry about setting the reloc
284
   address or the reloc symbol index.
285
286
   LOCAL_SYMS is a pointer to the swapped in local symbols.
287
288
   LOCAL_SECTIONS is an array giving the section in the input file
289
   corresponding to the st_shndx field of each local symbol.
290
291
   The global hash table entry for the global symbols can be found
292
   via elf_sym_hashes (input_bfd).
293
294
   When generating relocatable output, this function must handle
295
   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
296
   going to be the section symbol corresponding to the output
297
   section, which means that the addend must be adjusted
298
   accordingly.  */
299
300
static int
301
mt_elf_relocate_section
302
    (bfd *         output_bfd ATTRIBUTE_UNUSED,
303
     struct bfd_link_info *  info,
304
     bfd *         input_bfd,
305
     asection *        input_section,
306
     bfd_byte *        contents,
307
     Elf_Internal_Rela *     relocs,
308
     Elf_Internal_Sym *      local_syms,
309
     asection **       local_sections)
310
0
{
311
0
  Elf_Internal_Shdr *   symtab_hdr;
312
0
  struct elf_link_hash_entry ** sym_hashes;
313
0
  Elf_Internal_Rela *   rel;
314
0
  Elf_Internal_Rela *   relend;
315
316
0
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
317
0
  sym_hashes = elf_sym_hashes (input_bfd);
318
0
  relend     = relocs + input_section->reloc_count;
319
320
0
  for (rel = relocs; rel < relend; rel ++)
321
0
    {
322
0
      reloc_howto_type *     howto;
323
0
      unsigned long      r_symndx;
324
0
      Elf_Internal_Sym *     sym;
325
0
      asection *       sec;
326
0
      struct elf_link_hash_entry * h;
327
0
      bfd_vma        relocation;
328
0
      bfd_reloc_status_type    r;
329
0
      const char *       name = NULL;
330
0
      int        r_type;
331
332
0
      r_type = ELF32_R_TYPE (rel->r_info);
333
334
0
      r_symndx = ELF32_R_SYM (rel->r_info);
335
336
0
      howto  = mt_elf_howto_table + ELF32_R_TYPE (rel->r_info);
337
0
      h      = NULL;
338
0
      sym    = NULL;
339
0
      sec    = NULL;
340
341
0
      if (r_symndx < symtab_hdr->sh_info)
342
0
  {
343
0
    sym = local_syms + r_symndx;
344
0
    sec = local_sections [r_symndx];
345
0
    relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
346
347
0
    name = bfd_elf_string_from_elf_section
348
0
      (input_bfd, symtab_hdr->sh_link, sym->st_name);
349
0
    name = name == NULL ? bfd_section_name (sec) : name;
350
0
  }
351
0
      else
352
0
  {
353
0
    bool unresolved_reloc;
354
0
    bool warned, ignored;
355
356
0
    RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
357
0
           r_symndx, symtab_hdr, sym_hashes,
358
0
           h, sec, relocation,
359
0
           unresolved_reloc, warned, ignored);
360
361
0
    name = h->root.root.string;
362
0
  }
363
364
0
      if (sec != NULL && discarded_section (sec))
365
0
  RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
366
0
           rel, 1, relend, howto, 0, contents);
367
368
0
      if (bfd_link_relocatable (info))
369
0
  continue;
370
371
      /* Finally, the sole MT-specific part.  */
372
0
      switch (r_type)
373
0
  {
374
0
  case R_MT_HI16:
375
0
    r = mt_elf_relocate_hi16 (input_bfd, rel, contents, relocation);
376
0
    break;
377
0
  default:
378
0
    r = mt_final_link_relocate (howto, input_bfd, input_section,
379
0
            contents, rel, relocation);
380
0
    break;
381
0
  }
382
383
384
0
      if (r != bfd_reloc_ok)
385
0
  {
386
0
    const char * msg = (const char *) NULL;
387
388
0
    switch (r)
389
0
      {
390
0
      case bfd_reloc_overflow:
391
0
        (*info->callbacks->reloc_overflow)
392
0
    (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
393
0
     input_bfd, input_section, rel->r_offset);
394
0
        break;
395
396
0
      case bfd_reloc_undefined:
397
0
        (*info->callbacks->undefined_symbol)
398
0
    (info, name, input_bfd, input_section, rel->r_offset, true);
399
0
        break;
400
401
0
      case bfd_reloc_outofrange:
402
0
        msg = _("internal error: out of range error");
403
0
        break;
404
405
0
      case bfd_reloc_dangerous:
406
0
        msg = _("internal error: dangerous relocation");
407
0
        break;
408
409
0
      default:
410
0
        msg = _("internal error: unknown error");
411
0
        break;
412
0
      }
413
414
0
    if (msg)
415
0
      (*info->callbacks->warning) (info, msg, name, input_bfd,
416
0
           input_section, rel->r_offset);
417
0
  }
418
0
    }
419
420
0
  return true;
421
0
}
422
423
/* Look through the relocs for a section during the first phase.
424
   Since we don't do .gots or .plts, we just need to consider the
425
   virtual table relocs for gc.  */
426
427
static bool
428
mt_elf_check_relocs (bfd *abfd,
429
         struct bfd_link_info *info,
430
         asection *sec,
431
         const Elf_Internal_Rela *relocs)
432
0
{
433
0
  Elf_Internal_Shdr *symtab_hdr;
434
0
  struct elf_link_hash_entry **sym_hashes;
435
0
  const Elf_Internal_Rela *rel;
436
0
  const Elf_Internal_Rela *rel_end;
437
438
0
  if (bfd_link_relocatable (info))
439
0
    return true;
440
441
0
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
442
0
  sym_hashes = elf_sym_hashes (abfd);
443
444
0
  rel_end = relocs + sec->reloc_count;
445
0
  for (rel = relocs; rel < rel_end; rel++)
446
0
    {
447
0
      struct elf_link_hash_entry *h;
448
0
      unsigned long r_symndx;
449
450
0
      r_symndx = ELF32_R_SYM (rel->r_info);
451
0
      if (r_symndx < symtab_hdr->sh_info)
452
0
  h = NULL;
453
0
      else
454
0
  {
455
0
    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
456
0
    while (h->root.type == bfd_link_hash_indirect
457
0
     || h->root.type == bfd_link_hash_warning)
458
0
      h = (struct elf_link_hash_entry *) h->root.u.i.link;
459
0
  }
460
0
    }
461
462
0
  return true;
463
0
}
464
465
/* Return the MACH for an e_flags value.  */
466
467
static int
468
elf32_mt_machine (bfd *abfd)
469
487
{
470
487
  switch (elf_elfheader (abfd)->e_flags & EF_MT_CPU_MASK)
471
487
    {
472
2
    case EF_MT_CPU_MRISC: return bfd_mach_ms1;
473
20
    case EF_MT_CPU_MRISC2: return bfd_mach_mrisc2;
474
2
    case EF_MT_CPU_MS2:   return bfd_mach_ms2;
475
487
    }
476
477
463
  return bfd_mach_ms1;
478
487
}
479
480
static bool
481
mt_elf_object_p (bfd *abfd)
482
487
{
483
487
  bfd_default_set_arch_mach (abfd, bfd_arch_mt, elf32_mt_machine (abfd));
484
485
487
  return true;
486
487
}
487
488
/* Function to set the ELF flag bits.  */
489
490
static bool
491
mt_elf_set_private_flags (bfd *abfd, flagword flags)
492
0
{
493
0
  elf_elfheader (abfd)->e_flags = flags;
494
0
  elf_flags_init (abfd) = true;
495
0
  return true;
496
0
}
497
498
/* Merge backend specific data from an object file to the output
499
   object file when linking.  */
500
501
static bool
502
mt_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
503
0
{
504
0
  bfd *obfd = info->output_bfd;
505
0
  flagword old_flags, new_flags;
506
0
  bool ok = true;
507
508
  /* Check if we have the same endianness.  */
509
0
  if (!_bfd_generic_verify_endian_match (ibfd, info))
510
0
    return false;
511
512
  /* If they're not both mt, then merging is meaningless, so just
513
     don't do it.  */
514
0
  if (strcmp (ibfd->arch_info->arch_name, "mt") != 0)
515
0
    return true;
516
0
  if (strcmp (obfd->arch_info->arch_name, "mt") != 0)
517
0
    return true;
518
519
0
  new_flags = elf_elfheader (ibfd)->e_flags;
520
0
  old_flags = elf_elfheader (obfd)->e_flags;
521
522
#ifdef DEBUG
523
  _bfd_error_handler ("%pB: old_flags = 0x%.8x, new_flags = 0x%.8x, init = %s",
524
          ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
525
#endif
526
527
0
  if (!elf_flags_init (obfd))
528
0
    {
529
0
      old_flags = new_flags;
530
0
      elf_flags_init (obfd) = true;
531
0
    }
532
0
  else if ((new_flags & EF_MT_CPU_MASK) != (old_flags & EF_MT_CPU_MASK))
533
0
    {
534
      /* CPU has changed.  This is invalid, because MRISC, MRISC2 and
535
   MS2 are not subsets of each other.   */
536
0
      ok = false;
537
0
    }
538
539
0
  if (ok)
540
0
    {
541
0
      obfd->arch_info = ibfd->arch_info;
542
0
      elf_elfheader (obfd)->e_flags = old_flags;
543
0
    }
544
545
0
  return ok;
546
0
}
547
548
static bool
549
mt_elf_print_private_bfd_data (bfd *abfd, void *ptr)
550
10
{
551
10
  FILE *file = (FILE *) ptr;
552
10
  flagword flags;
553
554
10
  BFD_ASSERT (abfd != NULL && ptr != NULL);
555
556
  /* Print normal ELF private data.  */
557
10
  _bfd_elf_print_private_bfd_data (abfd, ptr);
558
559
10
  flags = elf_elfheader (abfd)->e_flags;
560
10
  fprintf (file, _("private flags = 0x%lx:"), (unsigned long) flags);
561
562
10
  switch (flags & EF_MT_CPU_MASK)
563
10
    {
564
0
    default:
565
0
    case EF_MT_CPU_MRISC:   fprintf (file, " ms1-16-002");  break;
566
10
    case EF_MT_CPU_MRISC2:  fprintf (file, " ms1-16-003"); break;
567
0
    case EF_MT_CPU_MS2:     fprintf (file, " ms2"); break;
568
10
    }
569
570
10
  fputc ('\n', file);
571
572
10
  return true;
573
10
}
574
575

576
#define TARGET_BIG_SYM   mt_elf32_vec
577
#define TARGET_BIG_NAME  "elf32-mt"
578
579
#define ELF_ARCH   bfd_arch_mt
580
#define ELF_MACHINE_CODE EM_MT
581
#define ELF_MAXPAGESIZE  1 /* No pages on the MT.  */
582
583
#define elf_info_to_howto_rel     NULL
584
#define elf_info_to_howto     mt_info_to_howto_rela
585
586
#define elf_backend_relocate_section    mt_elf_relocate_section
587
588
#define bfd_elf32_bfd_reloc_type_lookup   mt_reloc_type_lookup
589
#define bfd_elf32_bfd_reloc_name_lookup   mt_reloc_name_lookup
590
591
#define elf_backend_check_relocs    mt_elf_check_relocs
592
#define elf_backend_object_p      mt_elf_object_p
593
#define elf_backend_rela_normal     1
594
595
#define elf_backend_can_gc_sections   1
596
597
#define bfd_elf32_bfd_set_private_flags   mt_elf_set_private_flags
598
#define bfd_elf32_bfd_merge_private_bfd_data  mt_elf_merge_private_bfd_data
599
#define bfd_elf32_bfd_print_private_bfd_data  mt_elf_print_private_bfd_data
600
601
#include "elf32-target.h"