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-moxie.c
Line
Count
Source
1
/* moxie-specific support for 32-bit ELF.
2
   Copyright (C) 2009-2026 Free Software Foundation, Inc.
3
4
   Copied from elf32-fr30.c which is..
5
   Copyright (C) 1998-2026 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, R_MOXIE_NONE,
263
0
           howto, 0, contents);
264
265
0
      if (bfd_link_relocatable (info))
266
0
  continue;
267
268
0
      r = moxie_final_link_relocate (howto, input_bfd, input_section,
269
0
             contents, rel, relocation);
270
271
0
      if (r != bfd_reloc_ok)
272
0
  {
273
0
    const char * msg = NULL;
274
275
0
    switch (r)
276
0
      {
277
0
      case bfd_reloc_overflow:
278
0
        (*info->callbacks->reloc_overflow)
279
0
    (info, (h ? &h->root : NULL), name, howto->name,
280
0
     (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
281
0
        break;
282
283
0
      case bfd_reloc_undefined:
284
0
        (*info->callbacks->undefined_symbol)
285
0
    (info, name, input_bfd, input_section, rel->r_offset, true);
286
0
        break;
287
288
0
      case bfd_reloc_outofrange:
289
0
        msg = _("internal error: out of range error");
290
0
        break;
291
292
0
      case bfd_reloc_notsupported:
293
0
        msg = _("internal error: unsupported relocation error");
294
0
        break;
295
296
0
      case bfd_reloc_dangerous:
297
0
        msg = _("internal error: dangerous relocation");
298
0
        break;
299
300
0
      default:
301
0
        msg = _("internal error: unknown error");
302
0
        break;
303
0
      }
304
305
0
    if (msg)
306
0
      (*info->callbacks->warning) (info, msg, name, input_bfd,
307
0
           input_section, rel->r_offset);
308
0
  }
309
0
    }
310
311
0
  return true;
312
0
}
313

314
/* Look through the relocs for a section during the first phase.
315
   Since we don't do .gots or .plts, we just need to consider the
316
   virtual table relocs for gc.  */
317
318
static bool
319
moxie_elf_check_relocs (bfd *abfd,
320
      struct bfd_link_info *info,
321
      asection *sec,
322
      const Elf_Internal_Rela *relocs)
323
0
{
324
0
  Elf_Internal_Shdr *symtab_hdr;
325
0
  struct elf_link_hash_entry **sym_hashes;
326
0
  const Elf_Internal_Rela *rel;
327
0
  const Elf_Internal_Rela *rel_end;
328
329
0
  if (bfd_link_relocatable (info))
330
0
    return true;
331
332
0
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
333
0
  sym_hashes = elf_sym_hashes (abfd);
334
335
0
  rel_end = relocs + sec->reloc_count;
336
0
  for (rel = relocs; rel < rel_end; rel++)
337
0
    {
338
0
      struct elf_link_hash_entry *h;
339
0
      unsigned long r_symndx;
340
341
0
      r_symndx = ELF32_R_SYM (rel->r_info);
342
0
      if (r_symndx < symtab_hdr->sh_info)
343
0
  h = NULL;
344
0
      else
345
0
  {
346
0
    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
347
0
    while (h->root.type == bfd_link_hash_indirect
348
0
     || h->root.type == bfd_link_hash_warning)
349
0
      h = (struct elf_link_hash_entry *) h->root.u.i.link;
350
0
  }
351
0
    }
352
353
  return true;
354
0
}
355

356
#define ELF_ARCH    bfd_arch_moxie
357
#define ELF_MACHINE_CODE  EM_MOXIE
358
#define ELF_MACHINE_ALT1  EM_MOXIE_OLD
359
#define ELF_MAXPAGESIZE   0x1
360
361
#define TARGET_BIG_SYM    moxie_elf32_be_vec
362
#define TARGET_BIG_NAME   "elf32-bigmoxie"
363
#define TARGET_LITTLE_SYM moxie_elf32_le_vec
364
#define TARGET_LITTLE_NAME  "elf32-littlemoxie"
365
366
#define elf_info_to_howto_rel     NULL
367
#define elf_info_to_howto     moxie_info_to_howto_rela
368
#define elf_backend_relocate_section    moxie_elf_relocate_section
369
#define elf_backend_check_relocs    moxie_elf_check_relocs
370
371
#define elf_backend_can_gc_sections   1
372
#define elf_backend_rela_normal     1
373
374
#define bfd_elf32_bfd_reloc_type_lookup   moxie_reloc_type_lookup
375
#define bfd_elf32_bfd_reloc_name_lookup   moxie_reloc_name_lookup
376
377
#include "elf32-target.h"