Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/bfd/elf32-xgate.c
Line
Count
Source (jump to first uncovered line)
1
/* Freescale XGATE-specific support for 32-bit ELF
2
   Copyright (C) 2010-2025 Free Software Foundation, Inc.
3
   Contributed by Sean Keys(skeys@ipdatasys.com)
4
5
   This file is part of BFD, the Binary File Descriptor library.
6
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
22
#include "sysdep.h"
23
#include "bfd.h"
24
#include "bfdlink.h"
25
#include "libbfd.h"
26
#include "elf-bfd.h"
27
#include "elf/xgate.h"
28
#include "opcode/xgate.h"
29
#include "libiberty.h"
30
31
/* Forward declarations.  */
32
static bfd_reloc_status_type xgate_elf_ignore_reloc
33
  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
34
static bfd_reloc_status_type xgate_elf_special_reloc
35
  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
36
37
/* Use REL instead of RELA to save space */
38
#define USE_REL 1
39
40
static reloc_howto_type elf_xgate_howto_table[] =
41
{
42
  /* This reloc does nothing.  */
43
  HOWTO (R_XGATE_NONE, /* type */
44
   0, /* rightshift */
45
   0, /* size */
46
   0, /* bitsize */
47
   false, /* pc_relative */
48
   0, /* bitpos */
49
   complain_overflow_dont,/* complain_on_overflow */
50
   bfd_elf_generic_reloc, /* special_function */
51
   "R_XGATE_NONE", /* name */
52
   false, /* partial_inplace */
53
   0, /* src_mask */
54
   0, /* dst_mask */
55
   false), /* pcrel_offset */
56
57
  /* A 8 bit absolute relocation.  */
58
  HOWTO (R_XGATE_8, /* type */
59
   0, /* rightshift */
60
   1, /* size */
61
   8, /* bitsize */
62
   false, /* pc_relative */
63
   0, /* bitpos */
64
   complain_overflow_bitfield, /* complain_on_overflow */
65
   bfd_elf_generic_reloc, /* special_function */
66
   "R_XGATE_8", /* name */
67
   false, /* partial_inplace */
68
   0x00ff, /* src_mask */
69
   0x00ff, /* dst_mask */
70
   false), /* pcrel_offset */
71
72
  /* A 8 bit PC-rel relocation.  */
73
  HOWTO (R_XGATE_PCREL_8, /* type */
74
   0, /* rightshift */
75
   1, /* size */
76
   8, /* bitsize */
77
   true, /* pc_relative */
78
   0, /* bitpos */
79
   complain_overflow_bitfield, /* complain_on_overflow */
80
   bfd_elf_generic_reloc, /* special_function */
81
   "R_XGATE_PCREL_8", /* name */
82
   false, /* partial_inplace */
83
   0x00ff, /* src_mask */
84
   0x00ff, /* dst_mask */
85
   true), /* pcrel_offset */
86
87
  /* A 16 bit absolute relocation.  */
88
  HOWTO (R_XGATE_16, /* type */
89
   0, /* rightshift */
90
   2, /* size */
91
   16, /* bitsize */
92
   false, /* pc_relative */
93
   0, /* bitpos */
94
   complain_overflow_dont /*bitfield */, /* complain_on_overflow */
95
   bfd_elf_generic_reloc, /* special_function */
96
   "R_XGATE_16", /* name */
97
   false, /* partial_inplace */
98
   0xffff, /* src_mask */
99
   0xffff, /* dst_mask */
100
   false), /* pcrel_offset */
101
102
  /* A 32 bit absolute relocation.  This one is never used for the
103
     code relocation.  It's used by gas for -gstabs generation.  */
104
  HOWTO (R_XGATE_32, /* type */
105
   0, /* rightshift */
106
   4, /* size */
107
   32, /* bitsize */
108
   false, /* pc_relative */
109
   0, /* bitpos */
110
   complain_overflow_bitfield, /* complain_on_overflow */
111
   bfd_elf_generic_reloc, /* special_function */
112
   "R_XGATE_32", /* name */
113
   false, /* partial_inplace */
114
   0xffffffff, /* src_mask */
115
   0xffffffff, /* dst_mask */
116
   false), /* pcrel_offset */
117
118
  /* A 16 bit PC-rel relocation.  */
119
  HOWTO (R_XGATE_PCREL_16, /* type */
120
   0, /* rightshift */
121
   2, /* size */
122
   16, /* bitsize */
123
   true, /* pc_relative */
124
   0, /* bitpos */
125
   complain_overflow_dont, /* complain_on_overflow */
126
   bfd_elf_generic_reloc, /* special_function */
127
   "R_XGATE_PCREL_16", /* name */
128
   false, /* partial_inplace */
129
   0xffff, /* src_mask */
130
   0xffff, /* dst_mask */
131
   true), /* pcrel_offset */
132
133
  /* GNU extension to record C++ vtable hierarchy.  */
134
  HOWTO (R_XGATE_GNU_VTINHERIT, /* type */
135
   0, /* rightshift */
136
   2, /* size */
137
   0, /* bitsize */
138
   false, /* pc_relative */
139
   0, /* bitpos */
140
   complain_overflow_dont, /* complain_on_overflow */
141
   NULL, /* special_function */
142
   "R_XGATE_GNU_VTINHERIT", /* name */
143
   false, /* partial_inplace */
144
   0, /* src_mask */
145
   0, /* dst_mask */
146
   false), /* pcrel_offset */
147
148
  /* GNU extension to record C++ vtable member usage.  */
149
  HOWTO (R_XGATE_GNU_VTENTRY, /* type */
150
   0, /* rightshift */
151
   2, /* size */
152
   0, /* bitsize */
153
   false, /* pc_relative */
154
   0, /* bitpos */
155
   complain_overflow_dont, /* complain_on_overflow */
156
   _bfd_elf_rel_vtable_reloc_fn, /* special_function */
157
   "R_XGATE_GNU_VTENTRY", /* name */
158
   false, /* partial_inplace */
159
   0, /* src_mask */
160
   0, /* dst_mask */
161
   false), /* pcrel_offset */
162
163
  /* A 24 bit relocation.  */
164
  HOWTO (R_XGATE_24, /* type */
165
   0, /* rightshift */
166
   2, /* size */
167
   16, /* bitsize */
168
   false, /* pc_relative */
169
   0, /* bitpos */
170
   complain_overflow_dont, /* complain_on_overflow */
171
   bfd_elf_generic_reloc, /* special_function */
172
   "R_XGATE_IMM8_LO", /* name */
173
   false, /* partial_inplace */
174
   0x00ff, /* src_mask */
175
   0x00ff, /* dst_mask */
176
   false), /* pcrel_offset */
177
178
  /* A 16-bit low relocation.  */
179
  HOWTO (R_XGATE_LO16, /* type */
180
   8, /* rightshift */
181
   2, /* size */
182
   16, /* bitsize */
183
   false, /* pc_relative */
184
   0, /* bitpos */
185
   complain_overflow_dont, /* complain_on_overflow */
186
   bfd_elf_generic_reloc, /* special_function */
187
   "R_XGATE_IMM8_HI", /* name */
188
   false, /* partial_inplace */
189
   0x00ff, /* src_mask */
190
   0x00ff, /* dst_mask */
191
   false), /* pcrel_offset */
192
193
  /* A page relocation.  */
194
  HOWTO (R_XGATE_GPAGE, /* type */
195
   0, /* rightshift */
196
   1, /* size */
197
   8, /* bitsize */
198
   false, /* pc_relative */
199
   0, /* bitpos */
200
   complain_overflow_dont, /* complain_on_overflow */
201
   xgate_elf_special_reloc,/* special_function */
202
   "R_XGATE_GPAGE", /* name */
203
   false, /* partial_inplace */
204
   0x00ff, /* src_mask */
205
   0x00ff, /* dst_mask */
206
   false), /* pcrel_offset */
207
208
  /* A 9 bit absolute relocation.   */
209
  HOWTO (R_XGATE_PCREL_9, /* type */
210
   0, /* rightshift */
211
   2, /* size */
212
   9, /* bitsize */
213
   true, /* pc_relative */
214
   0, /* bitpos */
215
   complain_overflow_bitfield, /* complain_on_overflow */
216
   bfd_elf_generic_reloc, /* special_function */
217
   "R_XGATE_PCREL_9", /* name */
218
   false, /* partial_inplace */
219
   0xffff, /* src_mask */
220
   0xffff, /* dst_mask */
221
   true), /* pcrel_offset */
222
223
  /* A 8 bit absolute relocation (upper address).  */
224
  HOWTO (R_XGATE_PCREL_10, /* type */
225
   8, /* rightshift */
226
   1, /* size */
227
   10, /* bitsize */
228
   true, /* pc_relative */
229
   0, /* bitpos */
230
   complain_overflow_dont, /* complain_on_overflow */
231
   bfd_elf_generic_reloc, /* special_function */
232
   "R_XGATE_PCREL_10", /* name */
233
   false, /* partial_inplace */
234
   0x00ff, /* src_mask */
235
   0x00ff, /* dst_mask */
236
   true), /* pcrel_offset */
237
238
  /* A 8 bit absolute relocation.  */
239
  HOWTO (R_XGATE_IMM8_LO, /* type */
240
   0, /* rightshift */
241
   2, /* size */
242
   16, /* bitsize */
243
   false, /* pc_relative */
244
   0, /* bitpos */
245
   complain_overflow_dont, /* complain_on_overflow */
246
   bfd_elf_generic_reloc, /* special_function */
247
   "R_XGATE_IMM8_LO", /* name */
248
   false, /* partial_inplace */
249
   0xffff, /* src_mask */
250
   0xffff, /* dst_mask */
251
   false), /* pcrel_offset */
252
253
  /* A 16 bit absolute relocation (upper address).  */
254
  HOWTO (R_XGATE_IMM8_HI, /* type */
255
   8, /* rightshift */
256
   2, /* size */
257
   16, /* bitsize */
258
   false, /* pc_relative */
259
   0, /* bitpos */
260
   complain_overflow_dont, /* complain_on_overflow */
261
   bfd_elf_generic_reloc, /* special_function */
262
   "R_XGATE_IMM8_HI", /* name */
263
   false, /* partial_inplace */
264
   0x00ff, /* src_mask */
265
   0x00ff, /* dst_mask */
266
   false), /* pcrel_offset */
267
268
  /* A 3 bit absolute relocation.  */
269
  HOWTO (R_XGATE_IMM3, /* type */
270
   8, /* rightshift */
271
   2, /* size */
272
   16, /* bitsize */
273
   false, /* pc_relative */
274
   0, /* bitpos */
275
   complain_overflow_dont, /* complain_on_overflow */
276
   bfd_elf_generic_reloc, /* special_function */
277
   "R_XGATE_IMM3", /* name */
278
   false, /* partial_inplace */
279
   0x00ff, /* src_mask */
280
   0x00ff, /* dst_mask */
281
   false), /* pcrel_offset */
282
283
  /* A 4 bit absolute relocation.  */
284
  HOWTO (R_XGATE_IMM4, /* type */
285
   8, /* rightshift */
286
   2, /* size */
287
   16, /* bitsize */
288
   false, /* pc_relative */
289
   0, /* bitpos */
290
   complain_overflow_dont, /* complain_on_overflow */
291
   bfd_elf_generic_reloc, /* special_function */
292
   "R_XGATE_IMM4", /* name */
293
   false, /* partial_inplace */
294
   0x00ff, /* src_mask */
295
   0x00ff, /* dst_mask */
296
   false), /* pcrel_offset */
297
298
  /* A 5 bit absolute relocation.  */
299
  HOWTO (R_XGATE_IMM5, /* type */
300
   8, /* rightshift */
301
   2, /* size */
302
   16, /* bitsize */
303
   false, /* pc_relative */
304
   0, /* bitpos */
305
   complain_overflow_dont, /* complain_on_overflow */
306
   bfd_elf_generic_reloc, /* special_function */
307
   "R_XGATE_IMM5", /* name */
308
   false, /* partial_inplace */
309
   0x00ff, /* src_mask */
310
   0x00ff, /* dst_mask */
311
   false), /* pcrel_offset */
312
313
  /* Mark beginning of a jump instruction (any form).  */
314
  HOWTO (R_XGATE_RL_JUMP, /* type */
315
   0, /* rightshift */
316
   2, /* size */
317
   0, /* bitsize */
318
   false, /* pc_relative */
319
   0, /* bitpos */
320
   complain_overflow_dont, /* complain_on_overflow */
321
   xgate_elf_ignore_reloc, /* special_function */
322
   "R_XGATE_RL_JUMP", /* name */
323
   true, /* partial_inplace */
324
   0, /* src_mask */
325
   0, /* dst_mask */
326
   true), /* pcrel_offset */
327
328
  /* Mark beginning of Gcc relaxation group instruction.  */
329
  HOWTO (R_XGATE_RL_GROUP, /* type */
330
   0, /* rightshift */
331
   2, /* size */
332
   0, /* bitsize */
333
   false, /* pc_relative */
334
   0, /* bitpos */
335
   complain_overflow_dont, /* complain_on_overflow */
336
   xgate_elf_ignore_reloc, /* special_function */
337
   "R_XGATE_RL_GROUP", /* name */
338
   true, /* partial_inplace */
339
   0, /* src_mask */
340
   0, /* dst_mask */
341
   true), /* pcrel_offset */
342
};
343
344
/* Map BFD reloc types to XGATE ELF reloc types.  */
345
346
struct xgate_reloc_map
347
{
348
  bfd_reloc_code_real_type bfd_reloc_val;
349
  unsigned char elf_reloc_val;
350
};
351
352
static const struct xgate_reloc_map xgate_reloc_map[] =
353
{
354
  {BFD_RELOC_NONE, R_XGATE_NONE},
355
  {BFD_RELOC_8, R_XGATE_8},
356
  {BFD_RELOC_8_PCREL, R_XGATE_PCREL_8},
357
  {BFD_RELOC_16_PCREL, R_XGATE_PCREL_16},
358
  {BFD_RELOC_16, R_XGATE_16},
359
  {BFD_RELOC_32, R_XGATE_32},
360
361
  {BFD_RELOC_VTABLE_INHERIT, R_XGATE_GNU_VTINHERIT},
362
  {BFD_RELOC_VTABLE_ENTRY, R_XGATE_GNU_VTENTRY},
363
364
  {BFD_RELOC_XGATE_LO16, R_XGATE_LO16},
365
  {BFD_RELOC_XGATE_GPAGE, R_XGATE_GPAGE},
366
  {BFD_RELOC_XGATE_24, R_XGATE_24},
367
  {BFD_RELOC_XGATE_PCREL_9, R_XGATE_PCREL_9},
368
  {BFD_RELOC_XGATE_PCREL_10,  R_XGATE_PCREL_10},
369
  {BFD_RELOC_XGATE_IMM8_LO, R_XGATE_IMM8_LO},
370
  {BFD_RELOC_XGATE_IMM8_HI, R_XGATE_IMM8_HI},
371
  {BFD_RELOC_XGATE_IMM3, R_XGATE_IMM3},
372
  {BFD_RELOC_XGATE_IMM4, R_XGATE_IMM4},
373
  {BFD_RELOC_XGATE_IMM5, R_XGATE_IMM5},
374
375
  {BFD_RELOC_XGATE_RL_JUMP, R_XGATE_RL_JUMP},
376
  {BFD_RELOC_XGATE_RL_GROUP, R_XGATE_RL_GROUP},
377
};
378
379
static reloc_howto_type *
380
bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
381
         bfd_reloc_code_real_type code)
382
0
{
383
0
  unsigned int i;
384
385
0
  for (i = 0; i < ARRAY_SIZE (xgate_reloc_map); i++)
386
0
    if (xgate_reloc_map[i].bfd_reloc_val == code)
387
0
      return &elf_xgate_howto_table[xgate_reloc_map[i].elf_reloc_val];
388
389
0
  return NULL;
390
0
}
391
392
static reloc_howto_type *
393
bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
394
0
{
395
0
  unsigned int i;
396
397
0
  for (i = 0; i < ARRAY_SIZE (elf_xgate_howto_table); i++)
398
0
    if (elf_xgate_howto_table[i].name != NULL
399
0
  && strcasecmp (elf_xgate_howto_table[i].name, r_name) == 0)
400
0
      return &elf_xgate_howto_table[i];
401
402
0
  return NULL;
403
0
}
404
405
/* Set the howto pointer for an XGATE ELF reloc.  */
406
407
static bool
408
xgate_info_to_howto_rel (bfd *abfd,
409
       arelent *cache_ptr,
410
       Elf_Internal_Rela *dst)
411
0
{
412
0
  unsigned int r_type;
413
414
0
  r_type = ELF32_R_TYPE (dst->r_info);
415
0
  if (r_type >= (unsigned int) R_XGATE_max)
416
0
    {
417
      /* xgettext:c-format */
418
0
      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
419
0
        abfd, r_type);
420
0
      bfd_set_error (bfd_error_bad_value);
421
0
      return false;
422
0
    }
423
0
  cache_ptr->howto = &elf_xgate_howto_table[r_type];
424
0
  return true;
425
0
}
426
427
/* Specific sections:
428
 - The .page0 is a data section that is mapped in [0x0000..0x00FF].
429
   Page0 accesses are faster on the M68HC12.
430
 - The .vectors is the section that represents the interrupt
431
   vectors.
432
 - The .xgate section is starts in 0xE08800 or as xgate sees it 0x0800. */
433
static const struct bfd_elf_special_section elf32_xgate_special_sections[] =
434
{
435
  { STRING_COMMA_LEN (".eeprom"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
436
  { STRING_COMMA_LEN (".page0"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
437
  { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
438
  { STRING_COMMA_LEN (".vectors"), 0, SHT_PROGBITS, SHF_ALLOC },
439
/*{ STRING_COMMA_LEN (".xgate"),    0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
440
  TODO finish this implementation */
441
  { NULL, 0, 0, 0, 0 }
442
};
443
444
/* Hook called when reading symbols. */
445
446
static void
447
elf32_xgate_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
448
               asymbol *sym)
449
0
{
450
  /* Mark xgate symbols.  */
451
0
  ((elf_symbol_type *) sym)->internal_elf_sym.st_target_internal = 1;
452
0
}
453
454
/* This function is used for relocs which are only used for relaxing,
455
   which the linker should otherwise ignore.  */
456
457
static bfd_reloc_status_type
458
xgate_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
459
      arelent *reloc_entry,
460
      asymbol *symbol ATTRIBUTE_UNUSED,
461
      void *data ATTRIBUTE_UNUSED,
462
      asection *input_section,
463
      bfd *output_bfd,
464
      char **error_message ATTRIBUTE_UNUSED)
465
0
{
466
0
  if (output_bfd != NULL)
467
0
    reloc_entry->address += input_section->output_offset;
468
0
  return bfd_reloc_ok;
469
0
}
470
471
static bfd_reloc_status_type
472
xgate_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
473
       arelent *reloc_entry ATTRIBUTE_UNUSED,
474
       asymbol *symbol ATTRIBUTE_UNUSED,
475
       void *data ATTRIBUTE_UNUSED,
476
       asection *input_section ATTRIBUTE_UNUSED,
477
       bfd *output_bfd ATTRIBUTE_UNUSED,
478
       char **error_message ATTRIBUTE_UNUSED)
479
0
{
480
0
  abort ();
481
0
}
482
483
static bool
484
_bfd_xgate_elf_print_private_bfd_data (bfd *abfd, void *ptr)
485
14
{
486
14
  FILE *file = (FILE *) ptr;
487
488
14
  BFD_ASSERT (abfd != NULL && ptr != NULL);
489
490
  /* Print normal ELF private data.  */
491
14
  _bfd_elf_print_private_bfd_data (abfd, ptr);
492
493
  /* xgettext:c-format */
494
14
  fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
495
496
14
  if (elf_elfheader (abfd)->e_flags & E_XGATE_I32)
497
2
    fprintf (file, _("[abi=32-bit int, "));
498
12
  else
499
12
    fprintf (file, _("[abi=16-bit int, "));
500
501
14
  if (elf_elfheader (abfd)->e_flags & E_XGATE_F64)
502
1
    fprintf (file, _("64-bit double, "));
503
13
  else
504
13
    fprintf (file, _("32-bit double, "));
505
14
  if (elf_elfheader (abfd)->e_flags & EF_XGATE_MACH)
506
1
    fprintf (file, _("cpu=XGATE]"));
507
13
  else
508
13
    fprintf (file, _("error reading cpu type from elf private data"));
509
14
  fputc ('\n', file);
510
511
14
  return true;
512
14
}
513
514
#define ELF_ARCH           bfd_arch_xgate
515
#define ELF_MACHINE_CODE         EM_XGATE
516
517
#define ELF_MAXPAGESIZE          0x1000
518
519
#define TARGET_BIG_SYM           xgate_elf32_vec
520
#define TARGET_BIG_NAME          "elf32-xgate"
521
522
#define elf_info_to_howto_rel        xgate_info_to_howto_rel
523
#define elf_backend_special_sections       elf32_xgate_special_sections
524
#define elf_backend_symbol_processing      elf32_xgate_backend_symbol_processing
525
#define bfd_elf32_bfd_print_private_bfd_data _bfd_xgate_elf_print_private_bfd_data
526
527
#include "elf32-target.h"