Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/bfd/elf32-moxie.c
Line
Count
Source (jump to first uncovered line)
1
/* moxie-specific support for 32-bit ELF.
2
   Copyright (C) 2009-2025 Free Software Foundation, Inc.
3
4
   Copied from elf32-fr30.c which is..
5
   Copyright (C) 1998-2025 Free Software Foundation, Inc.
6
7
   This file is part of BFD, the Binary File Descriptor library.
8
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
19
   You should have received a copy of the GNU General Public License
20
   along with this program; if not, write to the Free Software
21
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22
   MA 02110-1301, USA.  */
23
24
#include "sysdep.h"
25
#include "bfd.h"
26
#include "libbfd.h"
27
#include "elf-bfd.h"
28
#include "elf/moxie.h"
29
30
/* Forward declarations.  */
31
32
static reloc_howto_type moxie_elf_howto_table [] =
33
{
34
  /* This reloc does nothing.  */
35
  HOWTO (R_MOXIE_NONE,    /* type */
36
   0,     /* rightshift */
37
   0,     /* size */
38
   0,     /* bitsize */
39
   false,     /* pc_relative */
40
   0,     /* bitpos */
41
   complain_overflow_dont, /* complain_on_overflow */
42
   bfd_elf_generic_reloc, /* special_function */
43
   "R_MOXIE_NONE",    /* name */
44
   false,     /* partial_inplace */
45
   0,     /* src_mask */
46
   0,     /* dst_mask */
47
   false),    /* pcrel_offset */
48
49
  /* A 32 bit absolute relocation.  */
50
  HOWTO (R_MOXIE_32,    /* type */
51
   0,     /* rightshift */
52
   4,     /* size */
53
   32,      /* bitsize */
54
   false,     /* pc_relative */
55
   0,     /* bitpos */
56
   complain_overflow_bitfield, /* complain_on_overflow */
57
   bfd_elf_generic_reloc, /* special_function */
58
   "R_MOXIE_32",    /* name */
59
   false,     /* partial_inplace */
60
   0x00000000,    /* src_mask */
61
   0xffffffff,    /* dst_mask */
62
   false),    /* pcrel_offset */
63
64
  /* A 10 bit PC-relative relocation.  */
65
  HOWTO (R_MOXIE_PCREL10, /* type.  */
66
   1,     /* rightshift.  */
67
   2,     /* size.  */
68
   10,      /* bitsize.  */
69
   true,      /* pc_relative.  */
70
   0,     /* bitpos.  */
71
   complain_overflow_signed, /* complain_on_overflow.  */
72
   bfd_elf_generic_reloc, /* special_function.  */
73
   "R_MOXIE_PCREL10",   /* name.  */
74
   false,     /* partial_inplace.  */
75
   0,     /* src_mask.  */
76
   0x000003FF,    /* dst_mask.  */
77
   true),     /* pcrel_offset.  */
78
};
79

80
/* Map BFD reloc types to MOXIE ELF reloc types.  */
81
82
struct moxie_reloc_map
83
{
84
  bfd_reloc_code_real_type bfd_reloc_val;
85
  unsigned int moxie_reloc_val;
86
};
87
88
static const struct moxie_reloc_map moxie_reloc_map [] =
89
{
90
  { BFD_RELOC_NONE,        R_MOXIE_NONE },
91
  { BFD_RELOC_32,        R_MOXIE_32 },
92
  { BFD_RELOC_MOXIE_10_PCREL,  R_MOXIE_PCREL10 },
93
};
94
95
static reloc_howto_type *
96
moxie_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
97
       bfd_reloc_code_real_type code)
98
0
{
99
0
  unsigned int i;
100
101
0
  for (i = sizeof (moxie_reloc_map) / sizeof (moxie_reloc_map[0]);
102
0
       i--;)
103
0
    if (moxie_reloc_map [i].bfd_reloc_val == code)
104
0
      return & moxie_elf_howto_table [moxie_reloc_map[i].moxie_reloc_val];
105
106
0
  return NULL;
107
0
}
108
109
static reloc_howto_type *
110
moxie_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
111
0
{
112
0
  unsigned int i;
113
114
0
  for (i = 0;
115
0
       i < sizeof (moxie_elf_howto_table) / sizeof (moxie_elf_howto_table[0]);
116
0
       i++)
117
0
    if (moxie_elf_howto_table[i].name != NULL
118
0
  && strcasecmp (moxie_elf_howto_table[i].name, r_name) == 0)
119
0
      return &moxie_elf_howto_table[i];
120
121
0
  return NULL;
122
0
}
123
124
/* Set the howto pointer for an MOXIE ELF reloc.  */
125
126
static bool
127
moxie_info_to_howto_rela (bfd *abfd,
128
        arelent *cache_ptr,
129
        Elf_Internal_Rela *dst)
130
0
{
131
0
  unsigned int r_type;
132
133
0
  r_type = ELF32_R_TYPE (dst->r_info);
134
0
  if (r_type >= (unsigned int) R_MOXIE_max)
135
0
    {
136
      /* xgettext:c-format */
137
0
      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
138
0
        abfd, r_type);
139
0
      bfd_set_error (bfd_error_bad_value);
140
0
      return false;
141
0
    }
142
0
  cache_ptr->howto = & moxie_elf_howto_table [r_type];
143
0
  return true;
144
0
}
145

146
/* Perform a single relocation.  By default we use the standard BFD
147
   routines, but a few relocs, we have to do them ourselves.  */
148
149
static bfd_reloc_status_type
150
moxie_final_link_relocate (reloc_howto_type *howto,
151
         bfd *input_bfd,
152
         asection *input_section,
153
         bfd_byte *contents,
154
         Elf_Internal_Rela *rel,
155
         bfd_vma relocation)
156
0
{
157
0
  bfd_reloc_status_type r = bfd_reloc_ok;
158
159
0
  switch (howto->type)
160
0
    {
161
0
    default:
162
0
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
163
0
            contents, rel->r_offset,
164
0
            relocation, rel->r_addend);
165
0
    }
166
167
0
  return r;
168
0
}
169

170
/* Relocate an MOXIE ELF section.
171
172
   The RELOCATE_SECTION function is called by the new ELF backend linker
173
   to handle the relocations for a section.
174
175
   The relocs are always passed as Rela structures; if the section
176
   actually uses Rel structures, the r_addend field will always be
177
   zero.
178
179
   This function is responsible for adjusting the section contents as
180
   necessary, and (if using Rela relocs and generating a relocatable
181
   output file) adjusting the reloc addend as necessary.
182
183
   This function does not have to worry about setting the reloc
184
   address or the reloc symbol index.
185
186
   LOCAL_SYMS is a pointer to the swapped in local symbols.
187
188
   LOCAL_SECTIONS is an array giving the section in the input file
189
   corresponding to the st_shndx field of each local symbol.
190
191
   The global hash table entry for the global symbols can be found
192
   via elf_sym_hashes (input_bfd).
193
194
   When generating relocatable output, this function must handle
195
   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
196
   going to be the section symbol corresponding to the output
197
   section, which means that the addend must be adjusted
198
   accordingly.  */
199
200
static int
201
moxie_elf_relocate_section (bfd *output_bfd,
202
          struct bfd_link_info *info,
203
          bfd *input_bfd,
204
          asection *input_section,
205
          bfd_byte *contents,
206
          Elf_Internal_Rela *relocs,
207
          Elf_Internal_Sym *local_syms,
208
          asection **local_sections)
209
0
{
210
0
  Elf_Internal_Shdr *symtab_hdr;
211
0
  struct elf_link_hash_entry **sym_hashes;
212
0
  Elf_Internal_Rela *rel;
213
0
  Elf_Internal_Rela *relend;
214
215
0
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
216
0
  sym_hashes = elf_sym_hashes (input_bfd);
217
0
  relend     = relocs + input_section->reloc_count;
218
219
0
  for (rel = relocs; rel < relend; rel ++)
220
0
    {
221
0
      reloc_howto_type *howto;
222
0
      unsigned long r_symndx;
223
0
      Elf_Internal_Sym *sym;
224
0
      asection *sec;
225
0
      struct elf_link_hash_entry *h;
226
0
      bfd_vma relocation;
227
0
      bfd_reloc_status_type r;
228
0
      const char *name;
229
0
      int r_type;
230
231
0
      r_type = ELF32_R_TYPE (rel->r_info);
232
0
      r_symndx = ELF32_R_SYM (rel->r_info);
233
0
      howto  = moxie_elf_howto_table + r_type;
234
0
      h      = NULL;
235
0
      sym    = NULL;
236
0
      sec    = NULL;
237
238
0
      if (r_symndx < symtab_hdr->sh_info)
239
0
  {
240
0
    sym = local_syms + r_symndx;
241
0
    sec = local_sections [r_symndx];
242
0
    relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
243
244
0
    name = bfd_elf_string_from_elf_section
245
0
      (input_bfd, symtab_hdr->sh_link, sym->st_name);
246
0
    name = name == NULL ? bfd_section_name (sec) : name;
247
0
  }
248
0
      else
249
0
  {
250
0
    bool unresolved_reloc, warned, ignored;
251
252
0
    RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
253
0
           r_symndx, symtab_hdr, sym_hashes,
254
0
           h, sec, relocation,
255
0
           unresolved_reloc, warned, ignored);
256
257
0
    name = h->root.root.string;
258
0
  }
259
260
0
      if (sec != NULL && discarded_section (sec))
261
0
  RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
262
0
           rel, 1, relend, howto, 0, contents);
263
264
0
      if (bfd_link_relocatable (info))
265
0
  continue;
266
267
0
      r = moxie_final_link_relocate (howto, input_bfd, input_section,
268
0
             contents, rel, relocation);
269
270
0
      if (r != bfd_reloc_ok)
271
0
  {
272
0
    const char * msg = NULL;
273
274
0
    switch (r)
275
0
      {
276
0
      case bfd_reloc_overflow:
277
0
        (*info->callbacks->reloc_overflow)
278
0
    (info, (h ? &h->root : NULL), name, howto->name,
279
0
     (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
280
0
        break;
281
282
0
      case bfd_reloc_undefined:
283
0
        (*info->callbacks->undefined_symbol)
284
0
    (info, name, input_bfd, input_section, rel->r_offset, true);
285
0
        break;
286
287
0
      case bfd_reloc_outofrange:
288
0
        msg = _("internal error: out of range error");
289
0
        break;
290
291
0
      case bfd_reloc_notsupported:
292
0
        msg = _("internal error: unsupported relocation error");
293
0
        break;
294
295
0
      case bfd_reloc_dangerous:
296
0
        msg = _("internal error: dangerous relocation");
297
0
        break;
298
299
0
      default:
300
0
        msg = _("internal error: unknown error");
301
0
        break;
302
0
      }
303
304
0
    if (msg)
305
0
      (*info->callbacks->warning) (info, msg, name, input_bfd,
306
0
           input_section, rel->r_offset);
307
0
  }
308
0
    }
309
310
0
  return true;
311
0
}
312

313
/* Return the section that should be marked against GC for a given
314
   relocation.  */
315
316
static asection *
317
moxie_elf_gc_mark_hook (asection *sec,
318
      struct bfd_link_info *info,
319
      Elf_Internal_Rela *rel,
320
      struct elf_link_hash_entry *h,
321
      Elf_Internal_Sym *sym)
322
0
{
323
0
  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
324
0
}
325
326
/* Look through the relocs for a section during the first phase.
327
   Since we don't do .gots or .plts, we just need to consider the
328
   virtual table relocs for gc.  */
329
330
static bool
331
moxie_elf_check_relocs (bfd *abfd,
332
      struct bfd_link_info *info,
333
      asection *sec,
334
      const Elf_Internal_Rela *relocs)
335
0
{
336
0
  Elf_Internal_Shdr *symtab_hdr;
337
0
  struct elf_link_hash_entry **sym_hashes;
338
0
  const Elf_Internal_Rela *rel;
339
0
  const Elf_Internal_Rela *rel_end;
340
341
0
  if (bfd_link_relocatable (info))
342
0
    return true;
343
344
0
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
345
0
  sym_hashes = elf_sym_hashes (abfd);
346
347
0
  rel_end = relocs + sec->reloc_count;
348
0
  for (rel = relocs; rel < rel_end; rel++)
349
0
    {
350
0
      struct elf_link_hash_entry *h;
351
0
      unsigned long r_symndx;
352
353
0
      r_symndx = ELF32_R_SYM (rel->r_info);
354
0
      if (r_symndx < symtab_hdr->sh_info)
355
0
  h = NULL;
356
0
      else
357
0
  {
358
0
    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
359
0
    while (h->root.type == bfd_link_hash_indirect
360
0
     || h->root.type == bfd_link_hash_warning)
361
0
      h = (struct elf_link_hash_entry *) h->root.u.i.link;
362
0
  }
363
0
    }
364
365
0
  return true;
366
0
}
367

368
#define ELF_ARCH    bfd_arch_moxie
369
#define ELF_MACHINE_CODE  EM_MOXIE
370
#define ELF_MACHINE_ALT1  EM_MOXIE_OLD
371
#define ELF_MAXPAGESIZE   0x1
372
373
#define TARGET_BIG_SYM    moxie_elf32_be_vec
374
#define TARGET_BIG_NAME   "elf32-bigmoxie"
375
#define TARGET_LITTLE_SYM moxie_elf32_le_vec
376
#define TARGET_LITTLE_NAME  "elf32-littlemoxie"
377
378
#define elf_info_to_howto_rel     NULL
379
#define elf_info_to_howto     moxie_info_to_howto_rela
380
#define elf_backend_relocate_section    moxie_elf_relocate_section
381
#define elf_backend_gc_mark_hook    moxie_elf_gc_mark_hook
382
#define elf_backend_check_relocs    moxie_elf_check_relocs
383
384
#define elf_backend_can_gc_sections   1
385
#define elf_backend_rela_normal     1
386
387
#define bfd_elf32_bfd_reloc_type_lookup   moxie_reloc_type_lookup
388
#define bfd_elf32_bfd_reloc_name_lookup   moxie_reloc_name_lookup
389
390
#include "elf32-target.h"