Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/bfd/elf32-fr30.c
Line
Count
Source (jump to first uncovered line)
1
/* FR30-specific support for 32-bit ELF.
2
   Copyright (C) 1998-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/fr30.h"
26
27
/* Forward declarations.  */
28
static bfd_reloc_status_type
29
fr30_elf_i20_reloc (bfd *, arelent *, asymbol *, void * data,
30
        asection *, bfd *, char **error_message);
31
static bfd_reloc_status_type
32
fr30_elf_i32_reloc (bfd *, arelent *, asymbol *, void *,
33
        asection *, bfd *, char **);
34
35
static reloc_howto_type fr30_elf_howto_table [] =
36
{
37
  /* This reloc does nothing.  */
38
  HOWTO (R_FR30_NONE,   /* type */
39
   0,     /* rightshift */
40
   0,     /* size */
41
   0,     /* bitsize */
42
   false,     /* pc_relative */
43
   0,     /* bitpos */
44
   complain_overflow_dont, /* complain_on_overflow */
45
   bfd_elf_generic_reloc, /* special_function */
46
   "R_FR30_NONE",   /* name */
47
   false,     /* partial_inplace */
48
   0,     /* src_mask */
49
   0,     /* dst_mask */
50
   false),    /* pcrel_offset */
51
52
  /* An 8 bit absolute relocation.  */
53
  HOWTO (R_FR30_8,    /* type */
54
   0,     /* rightshift */
55
   2,     /* size */
56
   8,     /* bitsize */
57
   false,     /* pc_relative */
58
   4,     /* bitpos */
59
   complain_overflow_bitfield, /* complain_on_overflow */
60
   bfd_elf_generic_reloc, /* special_function */
61
   "R_FR30_8",    /* name */
62
   false,     /* partial_inplace */
63
   0x0000,    /* src_mask */
64
   0x0ff0,    /* dst_mask */
65
   false),    /* pcrel_offset */
66
67
  /* A 20 bit absolute relocation.  */
68
  HOWTO (R_FR30_20,   /* type */
69
   0,     /* rightshift */
70
   4,     /* size */
71
   20,      /* bitsize */
72
   false,     /* pc_relative */
73
   0,     /* bitpos */
74
   complain_overflow_bitfield, /* complain_on_overflow */
75
   fr30_elf_i20_reloc,  /* special_function */
76
   "R_FR30_20",   /* name */
77
   false,     /* partial_inplace */
78
   0x00000000,    /* src_mask */
79
   0x00f0ffff,    /* dst_mask */
80
   false),    /* pcrel_offset */
81
82
  /* A 32 bit absolute relocation.  */
83
  HOWTO (R_FR30_32,   /* type */
84
   0,     /* rightshift */
85
   4,     /* size */
86
   32,      /* bitsize */
87
   false,     /* pc_relative */
88
   0,     /* bitpos */
89
   complain_overflow_bitfield, /* complain_on_overflow */
90
   bfd_elf_generic_reloc, /* special_function */
91
   "R_FR30_32",   /* name */
92
   false,     /* partial_inplace */
93
   0x00000000,    /* src_mask */
94
   0xffffffff,    /* dst_mask */
95
   false),    /* pcrel_offset */
96
97
  /* A 32 bit into 48 bits absolute relocation.  */
98
  HOWTO (R_FR30_48,   /* type */
99
   0,     /* rightshift */
100
   4,     /* size */
101
   32,      /* bitsize */
102
   false,     /* pc_relative */
103
   0,     /* bitpos */
104
   complain_overflow_bitfield, /* complain_on_overflow */
105
   fr30_elf_i32_reloc,  /* special_function */
106
   "R_FR30_48",   /* name */
107
   false,     /* partial_inplace */
108
   0x00000000,    /* src_mask */
109
   0xffffffff,    /* dst_mask */
110
   false),    /* pcrel_offset */
111
112
  /* A 6 bit absolute relocation.  */
113
  HOWTO (R_FR30_6_IN_4,   /* type */
114
   2,     /* rightshift */
115
   2,     /* size */
116
   6,     /* bitsize */
117
   false,     /* pc_relative */
118
   4,     /* bitpos */
119
   complain_overflow_unsigned, /* complain_on_overflow */
120
   bfd_elf_generic_reloc, /* special_function */
121
   "R_FR30_6_IN_4", /* name */
122
   false,     /* partial_inplace */
123
   0x0000,    /* src_mask */
124
   0x00f0,    /* dst_mask */
125
   false),    /* pcrel_offset */
126
127
  /* An 8 bit absolute relocation.  */
128
  HOWTO (R_FR30_8_IN_8,   /* type */
129
   0,     /* rightshift */
130
   2,     /* size */
131
   8,     /* bitsize */
132
   false,     /* pc_relative */
133
   4,     /* bitpos */
134
   complain_overflow_signed, /* complain_on_overflow */
135
   bfd_elf_generic_reloc,/* special_function */
136
   "R_FR30_8_IN_8", /* name */
137
   false,     /* partial_inplace */
138
   0x0000,    /* src_mask */
139
   0x0ff0,    /* dst_mask */
140
   false),    /* pcrel_offset */
141
142
  /* A 9 bit absolute relocation.  */
143
  HOWTO (R_FR30_9_IN_8,   /* type */
144
   1,     /* rightshift */
145
   2,     /* size */
146
   9,     /* bitsize */
147
   false,     /* pc_relative */
148
   4,     /* bitpos */
149
   complain_overflow_signed, /* complain_on_overflow */
150
   bfd_elf_generic_reloc,/* special_function */
151
   "R_FR30_9_IN_8", /* name */
152
   false,     /* partial_inplace */
153
   0x0000,    /* src_mask */
154
   0x0ff0,    /* dst_mask */
155
   false),    /* pcrel_offset */
156
157
  /* A 10 bit absolute relocation.  */
158
  HOWTO (R_FR30_10_IN_8,  /* type */
159
   2,     /* rightshift */
160
   2,     /* size */
161
   10,      /* bitsize */
162
   false,     /* pc_relative */
163
   4,     /* bitpos */
164
   complain_overflow_signed, /* complain_on_overflow */
165
   bfd_elf_generic_reloc,/* special_function */
166
   "R_FR30_10_IN_8",  /* name */
167
   false,     /* partial_inplace */
168
   0x0000,    /* src_mask */
169
   0x0ff0,    /* dst_mask */
170
   false),    /* pcrel_offset */
171
172
  /* A PC relative 9 bit relocation, right shifted by 1.  */
173
  HOWTO (R_FR30_9_PCREL,  /* type */
174
   1,     /* rightshift */
175
   2,     /* size */
176
   9,     /* bitsize */
177
   true,      /* pc_relative */
178
   0,     /* bitpos */
179
   complain_overflow_signed, /* complain_on_overflow */
180
   bfd_elf_generic_reloc, /* special_function */
181
   "R_FR30_9_PCREL",  /* name */
182
   false,     /* partial_inplace */
183
   0x0000,    /* src_mask */
184
   0x00ff,    /* dst_mask */
185
   false),    /* pcrel_offset */
186
187
  /* A PC relative 12 bit relocation, right shifted by 1.  */
188
  HOWTO (R_FR30_12_PCREL, /* type */
189
   1,     /* rightshift */
190
   2,     /* size */
191
   12,      /* bitsize */
192
   true,      /* pc_relative */
193
   0,     /* bitpos */
194
   complain_overflow_signed, /* complain_on_overflow */
195
   bfd_elf_generic_reloc, /* special_function */
196
   "R_FR30_12_PCREL", /* name */
197
   false,     /* partial_inplace */
198
   0x0000,    /* src_mask */
199
   0x07ff,    /* dst_mask */
200
   false),    /* pcrel_offset */
201
  /* GNU extension to record C++ vtable hierarchy */
202
  HOWTO (R_FR30_GNU_VTINHERIT, /* type */
203
   0,     /* rightshift */
204
   4,     /* size */
205
   0,     /* bitsize */
206
   false,     /* pc_relative */
207
   0,     /* bitpos */
208
   complain_overflow_dont, /* complain_on_overflow */
209
   NULL,      /* special_function */
210
   "R_FR30_GNU_VTINHERIT", /* name */
211
   false,     /* partial_inplace */
212
   0,     /* src_mask */
213
   0,     /* dst_mask */
214
   false),    /* pcrel_offset */
215
216
  /* GNU extension to record C++ vtable member usage */
217
  HOWTO (R_FR30_GNU_VTENTRY,   /* type */
218
   0,     /* rightshift */
219
   4,     /* size */
220
   0,     /* bitsize */
221
   false,     /* pc_relative */
222
   0,     /* bitpos */
223
   complain_overflow_dont, /* complain_on_overflow */
224
   _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
225
   "R_FR30_GNU_VTENTRY",   /* name */
226
   false,     /* partial_inplace */
227
   0,     /* src_mask */
228
   0,     /* dst_mask */
229
   false),    /* pcrel_offset */
230
};
231

232
/* Utility to actually perform an R_FR30_20 reloc.  */
233
234
static bfd_reloc_status_type
235
fr30_elf_i20_reloc (bfd *abfd,
236
        arelent *reloc_entry,
237
        asymbol *symbol,
238
        void * data,
239
        asection *input_section,
240
        bfd *output_bfd,
241
        char **error_message ATTRIBUTE_UNUSED)
242
0
{
243
0
  bfd_vma relocation;
244
0
  unsigned long x;
245
246
  /* This part is from bfd_elf_generic_reloc.  */
247
0
  if (output_bfd != (bfd *) NULL
248
0
      && (symbol->flags & BSF_SECTION_SYM) == 0
249
0
      && (! reloc_entry->howto->partial_inplace
250
0
    || reloc_entry->addend == 0))
251
0
    {
252
0
      reloc_entry->address += input_section->output_offset;
253
0
      return bfd_reloc_ok;
254
0
    }
255
256
0
  if (output_bfd != NULL)
257
    /* FIXME: See bfd_perform_relocation.  Is this right?  */
258
0
    return bfd_reloc_ok;
259
260
0
  relocation =
261
0
    symbol->value
262
0
    + symbol->section->output_section->vma
263
0
    + symbol->section->output_offset
264
0
    + reloc_entry->addend;
265
266
0
  if (relocation > (((bfd_vma) 1 << 20) - 1))
267
0
    return bfd_reloc_overflow;
268
269
0
  x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
270
0
  x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
271
0
  bfd_put_32 (abfd, (bfd_vma) x, (char *) data + reloc_entry->address);
272
273
0
  return bfd_reloc_ok;
274
0
}
275

276
/* Utility to actually perform a R_FR30_48 reloc.  */
277
278
static bfd_reloc_status_type
279
fr30_elf_i32_reloc (bfd *abfd,
280
        arelent *reloc_entry,
281
        asymbol *symbol,
282
        void * data,
283
        asection *input_section,
284
        bfd *output_bfd,
285
        char **error_message ATTRIBUTE_UNUSED)
286
0
{
287
0
  bfd_vma relocation;
288
289
  /* This part is from bfd_elf_generic_reloc.  */
290
0
  if (output_bfd != (bfd *) NULL
291
0
      && (symbol->flags & BSF_SECTION_SYM) == 0
292
0
      && (! reloc_entry->howto->partial_inplace
293
0
    || reloc_entry->addend == 0))
294
0
    {
295
0
      reloc_entry->address += input_section->output_offset;
296
0
      return bfd_reloc_ok;
297
0
    }
298
299
0
  if (output_bfd != NULL)
300
    /* FIXME: See bfd_perform_relocation.  Is this right?  */
301
0
    return bfd_reloc_ok;
302
303
0
  relocation =
304
0
    symbol->value
305
0
    + symbol->section->output_section->vma
306
0
    + symbol->section->output_offset
307
0
    + reloc_entry->addend;
308
309
0
  bfd_put_32 (abfd, relocation, (char *) data + reloc_entry->address + 2);
310
311
0
  return bfd_reloc_ok;
312
0
}
313

314
/* Map BFD reloc types to FR30 ELF reloc types.  */
315
316
struct fr30_reloc_map
317
{
318
  bfd_reloc_code_real_type bfd_reloc_val;
319
  unsigned int fr30_reloc_val;
320
};
321
322
static const struct fr30_reloc_map fr30_reloc_map [] =
323
{
324
  { BFD_RELOC_NONE,       R_FR30_NONE },
325
  { BFD_RELOC_8,        R_FR30_8 },
326
  { BFD_RELOC_FR30_20,        R_FR30_20 },
327
  { BFD_RELOC_32,       R_FR30_32 },
328
  { BFD_RELOC_FR30_48,        R_FR30_48 },
329
  { BFD_RELOC_FR30_6_IN_4,    R_FR30_6_IN_4 },
330
  { BFD_RELOC_FR30_8_IN_8,    R_FR30_8_IN_8 },
331
  { BFD_RELOC_FR30_9_IN_8,    R_FR30_9_IN_8 },
332
  { BFD_RELOC_FR30_10_IN_8,   R_FR30_10_IN_8 },
333
  { BFD_RELOC_FR30_9_PCREL,   R_FR30_9_PCREL },
334
  { BFD_RELOC_FR30_12_PCREL,  R_FR30_12_PCREL },
335
  { BFD_RELOC_VTABLE_INHERIT, R_FR30_GNU_VTINHERIT },
336
  { BFD_RELOC_VTABLE_ENTRY,   R_FR30_GNU_VTENTRY },
337
};
338
339
static reloc_howto_type *
340
fr30_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
341
      bfd_reloc_code_real_type code)
342
0
{
343
0
  unsigned int i;
344
345
0
  for (i = sizeof (fr30_reloc_map) / sizeof (fr30_reloc_map[0]);
346
0
       i--;)
347
0
    if (fr30_reloc_map [i].bfd_reloc_val == code)
348
0
      return & fr30_elf_howto_table [fr30_reloc_map[i].fr30_reloc_val];
349
350
0
  return NULL;
351
0
}
352
353
static reloc_howto_type *
354
fr30_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
355
0
{
356
0
  unsigned int i;
357
358
0
  for (i = 0;
359
0
       i < sizeof (fr30_elf_howto_table) / sizeof (fr30_elf_howto_table[0]);
360
0
       i++)
361
0
    if (fr30_elf_howto_table[i].name != NULL
362
0
  && strcasecmp (fr30_elf_howto_table[i].name, r_name) == 0)
363
0
      return &fr30_elf_howto_table[i];
364
365
0
  return NULL;
366
0
}
367
368
/* Set the howto pointer for an FR30 ELF reloc.  */
369
370
static bool
371
fr30_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
372
       arelent *cache_ptr,
373
       Elf_Internal_Rela *dst)
374
0
{
375
0
  unsigned int r_type;
376
377
0
  r_type = ELF32_R_TYPE (dst->r_info);
378
0
  if (r_type >= (unsigned int) R_FR30_max)
379
0
    {
380
      /* xgettext:c-format */
381
0
      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
382
0
        abfd, r_type);
383
0
      bfd_set_error (bfd_error_bad_value);
384
0
      return false;
385
0
    }
386
0
  cache_ptr->howto = & fr30_elf_howto_table [r_type];
387
0
  return true;
388
0
}
389

390
/* Perform a single relocation.  By default we use the standard BFD
391
   routines, but a few relocs, we have to do them ourselves.  */
392
393
static bfd_reloc_status_type
394
fr30_final_link_relocate (reloc_howto_type *howto,
395
        bfd *input_bfd,
396
        asection *input_section,
397
        bfd_byte *contents,
398
        Elf_Internal_Rela *rel,
399
        bfd_vma relocation)
400
0
{
401
0
  bfd_reloc_status_type r = bfd_reloc_ok;
402
0
  bfd_vma x;
403
0
  bfd_signed_vma srel;
404
405
0
  switch (howto->type)
406
0
    {
407
0
    case R_FR30_20:
408
0
      contents   += rel->r_offset;
409
0
      relocation += rel->r_addend;
410
411
0
      if (relocation > ((1 << 20) - 1))
412
0
  return bfd_reloc_overflow;
413
414
0
      x = bfd_get_32 (input_bfd, contents);
415
0
      x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
416
0
      bfd_put_32 (input_bfd, x, contents);
417
0
      break;
418
419
0
    case R_FR30_48:
420
0
      contents   += rel->r_offset + 2;
421
0
      relocation += rel->r_addend;
422
0
      bfd_put_32 (input_bfd, relocation, contents);
423
0
      break;
424
425
0
    case R_FR30_9_PCREL:
426
0
      contents   += rel->r_offset + 1;
427
0
      srel = (bfd_signed_vma) relocation;
428
0
      srel += rel->r_addend;
429
0
      srel -= rel->r_offset;
430
0
      srel -= 2;  /* Branch instructions add 2 to the PC...  */
431
0
      srel -= (input_section->output_section->vma +
432
0
         input_section->output_offset);
433
434
0
      if (srel & 1)
435
0
  return bfd_reloc_outofrange;
436
0
      if (srel > ((1 << 8) - 1) || (srel < - (1 << 8)))
437
0
  return bfd_reloc_overflow;
438
439
0
      bfd_put_8 (input_bfd, srel >> 1, contents);
440
0
      break;
441
442
0
    case R_FR30_12_PCREL:
443
0
      contents   += rel->r_offset;
444
0
      srel = (bfd_signed_vma) relocation;
445
0
      srel += rel->r_addend;
446
0
      srel -= rel->r_offset;
447
0
      srel -= 2; /* Branch instructions add 2 to the PC...  */
448
0
      srel -= (input_section->output_section->vma +
449
0
         input_section->output_offset);
450
451
0
      if (srel & 1)
452
0
  return bfd_reloc_outofrange;
453
0
      if (srel > ((1 << 11) - 1) || (srel < - (1 << 11)))
454
0
    return bfd_reloc_overflow;
455
456
0
      x = bfd_get_16 (input_bfd, contents);
457
0
      x = (x & 0xf800) | ((srel >> 1) & 0x7ff);
458
0
      bfd_put_16 (input_bfd, x, contents);
459
0
      break;
460
461
0
    default:
462
0
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
463
0
            contents, rel->r_offset,
464
0
            relocation, rel->r_addend);
465
0
    }
466
467
0
  return r;
468
0
}
469

470
/* Relocate an FR30 ELF section.
471
472
   The RELOCATE_SECTION function is called by the new ELF backend linker
473
   to handle the relocations for a section.
474
475
   The relocs are always passed as Rela structures; if the section
476
   actually uses Rel structures, the r_addend field will always be
477
   zero.
478
479
   This function is responsible for adjusting the section contents as
480
   necessary, and (if using Rela relocs and generating a relocatable
481
   output file) adjusting the reloc addend as necessary.
482
483
   This function does not have to worry about setting the reloc
484
   address or the reloc symbol index.
485
486
   LOCAL_SYMS is a pointer to the swapped in local symbols.
487
488
   LOCAL_SECTIONS is an array giving the section in the input file
489
   corresponding to the st_shndx field of each local symbol.
490
491
   The global hash table entry for the global symbols can be found
492
   via elf_sym_hashes (input_bfd).
493
494
   When generating relocatable output, this function must handle
495
   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
496
   going to be the section symbol corresponding to the output
497
   section, which means that the addend must be adjusted
498
   accordingly.  */
499
500
static int
501
fr30_elf_relocate_section (bfd *output_bfd,
502
         struct bfd_link_info *info,
503
         bfd *input_bfd,
504
         asection *input_section,
505
         bfd_byte *contents,
506
         Elf_Internal_Rela *relocs,
507
         Elf_Internal_Sym *local_syms,
508
         asection **local_sections)
509
0
{
510
0
  Elf_Internal_Shdr *symtab_hdr;
511
0
  struct elf_link_hash_entry **sym_hashes;
512
0
  Elf_Internal_Rela *rel;
513
0
  Elf_Internal_Rela *relend;
514
515
0
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
516
0
  sym_hashes = elf_sym_hashes (input_bfd);
517
0
  relend     = relocs + input_section->reloc_count;
518
519
0
  for (rel = relocs; rel < relend; rel ++)
520
0
    {
521
0
      reloc_howto_type *howto;
522
0
      unsigned long r_symndx;
523
0
      Elf_Internal_Sym *sym;
524
0
      asection *sec;
525
0
      struct elf_link_hash_entry *h;
526
0
      bfd_vma relocation;
527
0
      bfd_reloc_status_type r;
528
0
      const char *name;
529
0
      int r_type;
530
531
0
      r_type = ELF32_R_TYPE (rel->r_info);
532
533
0
      if (   r_type == R_FR30_GNU_VTINHERIT
534
0
    || r_type == R_FR30_GNU_VTENTRY)
535
0
  continue;
536
537
0
      r_symndx = ELF32_R_SYM (rel->r_info);
538
539
0
      howto  = fr30_elf_howto_table + ELF32_R_TYPE (rel->r_info);
540
0
      h      = NULL;
541
0
      sym    = NULL;
542
0
      sec    = NULL;
543
544
0
      if (r_symndx < symtab_hdr->sh_info)
545
0
  {
546
0
    sym = local_syms + r_symndx;
547
0
    sec = local_sections [r_symndx];
548
0
    relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
549
550
0
    name = bfd_elf_string_from_elf_section
551
0
      (input_bfd, symtab_hdr->sh_link, sym->st_name);
552
0
    name = name == NULL ? bfd_section_name (sec) : name;
553
0
  }
554
0
      else
555
0
  {
556
0
    bool unresolved_reloc, warned, ignored;
557
558
0
    RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
559
0
           r_symndx, symtab_hdr, sym_hashes,
560
0
           h, sec, relocation,
561
0
           unresolved_reloc, warned, ignored);
562
563
0
    name = h->root.root.string;
564
0
  }
565
566
0
      if (sec != NULL && discarded_section (sec))
567
0
  RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
568
0
           rel, 1, relend, howto, 0, contents);
569
570
0
      if (bfd_link_relocatable (info))
571
0
  continue;
572
573
0
      r = fr30_final_link_relocate (howto, input_bfd, input_section,
574
0
             contents, rel, relocation);
575
576
0
      if (r != bfd_reloc_ok)
577
0
  {
578
0
    const char * msg = (const char *) NULL;
579
580
0
    switch (r)
581
0
      {
582
0
      case bfd_reloc_overflow:
583
0
        (*info->callbacks->reloc_overflow)
584
0
    (info, (h ? &h->root : NULL), name, howto->name,
585
0
     (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
586
0
        break;
587
588
0
      case bfd_reloc_undefined:
589
0
        (*info->callbacks->undefined_symbol)
590
0
    (info, name, input_bfd, input_section, rel->r_offset, true);
591
0
        break;
592
593
0
      case bfd_reloc_outofrange:
594
0
        msg = _("internal error: out of range error");
595
0
        break;
596
597
0
      case bfd_reloc_notsupported:
598
0
        msg = _("internal error: unsupported relocation error");
599
0
        break;
600
601
0
      case bfd_reloc_dangerous:
602
0
        msg = _("internal error: dangerous relocation");
603
0
        break;
604
605
0
      default:
606
0
        msg = _("internal error: unknown error");
607
0
        break;
608
0
      }
609
610
0
    if (msg)
611
0
      (*info->callbacks->warning) (info, msg, name, input_bfd,
612
0
           input_section, rel->r_offset);
613
0
  }
614
0
    }
615
616
0
  return true;
617
0
}
618

619
/* Return the section that should be marked against GC for a given
620
   relocation.  */
621
622
static asection *
623
fr30_elf_gc_mark_hook (asection *sec,
624
           struct bfd_link_info *info,
625
           Elf_Internal_Rela *rel,
626
           struct elf_link_hash_entry *h,
627
           Elf_Internal_Sym *sym)
628
0
{
629
0
  if (h != NULL)
630
0
    switch (ELF32_R_TYPE (rel->r_info))
631
0
      {
632
0
      case R_FR30_GNU_VTINHERIT:
633
0
      case R_FR30_GNU_VTENTRY:
634
0
  return NULL;
635
0
      }
636
637
0
  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
638
0
}
639
640
/* Look through the relocs for a section during the first phase.
641
   Since we don't do .gots or .plts, we just need to consider the
642
   virtual table relocs for gc.  */
643
644
static bool
645
fr30_elf_check_relocs (bfd *abfd,
646
           struct bfd_link_info *info,
647
           asection *sec,
648
           const Elf_Internal_Rela *relocs)
649
0
{
650
0
  Elf_Internal_Shdr *symtab_hdr;
651
0
  struct elf_link_hash_entry **sym_hashes;
652
0
  const Elf_Internal_Rela *rel;
653
0
  const Elf_Internal_Rela *rel_end;
654
655
0
  if (bfd_link_relocatable (info))
656
0
    return true;
657
658
0
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
659
0
  sym_hashes = elf_sym_hashes (abfd);
660
661
0
  rel_end = relocs + sec->reloc_count;
662
0
  for (rel = relocs; rel < rel_end; rel++)
663
0
    {
664
0
      struct elf_link_hash_entry *h;
665
0
      unsigned long r_symndx;
666
667
0
      r_symndx = ELF32_R_SYM (rel->r_info);
668
0
      if (r_symndx < symtab_hdr->sh_info)
669
0
  h = NULL;
670
0
      else
671
0
  {
672
0
    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
673
0
    while (h->root.type == bfd_link_hash_indirect
674
0
     || h->root.type == bfd_link_hash_warning)
675
0
      h = (struct elf_link_hash_entry *) h->root.u.i.link;
676
0
  }
677
678
0
      switch (ELF32_R_TYPE (rel->r_info))
679
0
  {
680
  /* This relocation describes the C++ object vtable hierarchy.
681
     Reconstruct it for later use during GC.  */
682
0
  case R_FR30_GNU_VTINHERIT:
683
0
    if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
684
0
      return false;
685
0
    break;
686
687
  /* This relocation describes which C++ vtable entries are actually
688
     used.  Record for later use during GC.  */
689
0
  case R_FR30_GNU_VTENTRY:
690
0
    if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
691
0
      return false;
692
0
    break;
693
0
  }
694
0
    }
695
696
0
  return true;
697
0
}
698

699
#define ELF_ARCH    bfd_arch_fr30
700
#define ELF_MACHINE_CODE  EM_FR30
701
#define ELF_MACHINE_ALT1  EM_CYGNUS_FR30
702
#define ELF_MAXPAGESIZE   0x1000
703
704
#define TARGET_BIG_SYM    fr30_elf32_vec
705
#define TARGET_BIG_NAME   "elf32-fr30"
706
707
#define elf_info_to_howto_rel     NULL
708
#define elf_info_to_howto     fr30_info_to_howto_rela
709
#define elf_backend_relocate_section    fr30_elf_relocate_section
710
#define elf_backend_gc_mark_hook    fr30_elf_gc_mark_hook
711
#define elf_backend_check_relocs    fr30_elf_check_relocs
712
713
#define elf_backend_can_gc_sections   1
714
#define elf_backend_rela_normal     1
715
716
#define bfd_elf32_bfd_reloc_type_lookup   fr30_reloc_type_lookup
717
#define bfd_elf32_bfd_reloc_name_lookup   fr30_reloc_name_lookup
718
719
#include "elf32-target.h"