Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/bfd/elf32-s12z.c
Line
Count
Source (jump to first uncovered line)
1
/* Freescale S12Z-specific support for 32-bit ELF
2
   Copyright (C) 1999-2025 Free Software Foundation, Inc.
3
   (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.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
28
#include "elf/s12z.h"
29
30
/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1.  */
31
0
#define OCTETS_PER_BYTE(ABFD, SEC) 1
32
33
/* Relocation functions.  */
34
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
35
  (bfd *, bfd_reloc_code_real_type);
36
static bool s12z_info_to_howto_rel
37
  (bfd *, arelent *, Elf_Internal_Rela *);
38
39
static bfd_reloc_status_type
40
opru18_reloc (bfd *abfd, arelent *reloc_entry, struct bfd_symbol *symbol,
41
        void *data, asection *input_section ATTRIBUTE_UNUSED,
42
        bfd *output ATTRIBUTE_UNUSED, char **msg ATTRIBUTE_UNUSED)
43
0
{
44
  /* This reloc is used for 18 bit General Operand Addressing Postbyte in the
45
     INST opru18 form.  This is an 18 bit reloc, but the most significant bit
46
     is shifted one place to the left of where it would normally be.  See
47
     Appendix A.4 of the S12Z reference manual.  */
48
49
0
  bfd_size_type octets = (reloc_entry->address
50
0
        * OCTETS_PER_BYTE (abfd, input_section));
51
0
  bfd_vma result = bfd_get_24 (abfd, (unsigned char *) data + octets);
52
0
  bfd_vma val = bfd_asymbol_value (symbol);
53
54
  /* Keep the wanted bits and discard the rest.  */
55
0
  result &= 0xFA0000;
56
57
0
  val += symbol->section->output_section->vma;
58
0
  val += symbol->section->output_offset;
59
60
  /* The lowest 17 bits are copied verbatim.  */
61
0
  result |= val & 0x1FFFF;
62
63
  /* The 18th bit is put into the 19th position.  */
64
0
  result |= (val & 0x020000) << 1;
65
66
0
  bfd_put_24 (abfd, result, (unsigned char *) data + octets);
67
68
0
  return bfd_reloc_ok;
69
0
}
70
71
72
static bfd_reloc_status_type
73
shift_addend_reloc (bfd *abfd, arelent *reloc_entry, struct bfd_symbol *symbol ATTRIBUTE_UNUSED,
74
        void *data ATTRIBUTE_UNUSED, asection *input_section ATTRIBUTE_UNUSED,
75
        bfd *output ATTRIBUTE_UNUSED, char **msg ATTRIBUTE_UNUSED)
76
0
{
77
  /* This is a really peculiar reloc, which is done for compatibility
78
     with the Freescale toolchain.
79
80
     That toolchain appears to (ab)use the lowest 15 bits of the addend for
81
     the purpose of holding flags.  The purpose of these flags are unknown.
82
     So in this function, when writing the bfd we left shift the addend by
83
     15, and when reading we right shift it by 15 (discarding the lower bits).
84
85
     This allows the linker to work with object files generated by Freescale,
86
     as well as by Gas.  */
87
88
0
  if (abfd->is_linker_input)
89
0
    reloc_entry->addend >>= 15;
90
0
  else
91
0
    reloc_entry->addend <<= 15;
92
93
0
  return bfd_reloc_continue;
94
0
}
95
96
#define USE_REL 0
97
98
static reloc_howto_type elf_s12z_howto_table[] =
99
{
100
  /* This reloc does nothing.  */
101
  HOWTO (R_S12Z_NONE, /* type */
102
   0,     /* rightshift */
103
   0,     /* size */
104
   0,     /* bitsize */
105
   false,     /* pc_relative */
106
   0,     /* bitpos */
107
   complain_overflow_dont,/* complain_on_overflow */
108
   bfd_elf_generic_reloc, /* special_function */
109
   "R_S12Z_NONE", /* name */
110
   false,     /* partial_inplace */
111
   0,     /* src_mask */
112
   0,     /* dst_mask */
113
   false),    /* pcrel_offset */
114
115
  /* A 24 bit absolute relocation emitted by the OPR mode operands  */
116
  HOWTO (R_S12Z_OPR,        /* type */
117
   0,     /* rightshift */
118
   3,     /* size */
119
   24,      /* bitsize */
120
   false,     /* pc_relative */
121
   0,     /* bitpos */
122
   complain_overflow_bitfield,  /* complain_on_overflow */
123
   shift_addend_reloc,
124
   "R_S12Z_OPR",  /* name */
125
   false,     /* partial_inplace */
126
   0x00ffffff,            /* src_mask */
127
   0x00ffffff,    /* dst_mask */
128
   false),    /* pcrel_offset */
129
130
  /* The purpose of this reloc is not known */
131
  HOWTO (R_S12Z_UKNWN_2,  /* type */
132
   0,     /* rightshift */
133
   0,     /* size */
134
   0,     /* bitsize */
135
   false,     /* pc_relative */
136
   0,     /* bitpos */
137
   complain_overflow_dont,/* complain_on_overflow */
138
   bfd_elf_generic_reloc, /* special_function */
139
   "R_S12Z_UKNWN_2",  /* name */
140
   false,     /* partial_inplace */
141
   0,     /* src_mask */
142
   0,     /* dst_mask */
143
   false),    /* pcrel_offset */
144
145
  /* A 15 bit PC-rel relocation */
146
  HOWTO (R_S12Z_PCREL_7_15, /* type */
147
   0,     /* rightshift */
148
   2,     /* size */
149
   15,      /* bitsize */
150
   true,      /* pc_relative */
151
   0,     /* bitpos */
152
   complain_overflow_bitfield,  /* complain_on_overflow */
153
   shift_addend_reloc,
154
   "R_S12Z_PCREL_7_15", /* name */
155
   false,     /* partial_inplace */
156
   0x00,                  /* src_mask */
157
   0x007fff,    /* dst_mask */
158
   true),     /* pcrel_offset */
159
160
  /* A 24 bit absolute relocation emitted by EXT24 mode operands */
161
  HOWTO (R_S12Z_EXT24,        /* type */
162
   0,     /* rightshift */
163
   3,     /* size */
164
   24,      /* bitsize */
165
   false,     /* pc_relative */
166
   0,     /* bitpos */
167
   complain_overflow_bitfield,  /* complain_on_overflow */
168
   bfd_elf_generic_reloc, /* special_function */
169
   "R_S12Z_EXT24",  /* name */
170
   false,     /* partial_inplace */
171
   0x00000000,            /* src_mask */
172
   0x00ffffff,    /* dst_mask */
173
   false),    /* pcrel_offset */
174
175
  /* An 18 bit absolute relocation */
176
  HOWTO (R_S12Z_EXT18,        /* type */
177
   0,     /* rightshift */
178
   3,     /* size */
179
   18,      /* bitsize */
180
   false,     /* pc_relative */
181
   0,     /* bitpos */
182
   complain_overflow_bitfield,  /* complain_on_overflow */
183
   opru18_reloc,          /* special_function */
184
   "R_S12Z_EXT18",  /* name */
185
   false,     /* partial_inplace */
186
   0x00000000,            /* src_mask */
187
   0x0005ffff,    /* dst_mask */
188
   false),    /* pcrel_offset */
189
190
  /* A 32 bit absolute relocation.   This kind of relocation is
191
     schizophrenic - Although they appear in sections named .rela.debug.*
192
     in some sections they behave as RELA relocs, but in others they have
193
     an added of zero and behave as REL.
194
195
     It is not recommended that new code  emits this reloc.   It is here
196
     only to support existing elf files generated by third party
197
     applications.  */
198
199
  HOWTO (R_S12Z_CW32,        /* type */
200
   0,     /* rightshift */
201
   4,     /* size */
202
   32,      /* bitsize */
203
   false,     /* pc_relative */
204
   0,     /* bitpos */
205
   complain_overflow_bitfield,  /* complain_on_overflow */
206
   bfd_elf_generic_reloc, /* special_function */
207
   "R_S12Z_CW32", /* name */
208
   false,     /* partial_inplace */
209
   0xffffffff,            /* src_mask */
210
   0xffffffff,    /* dst_mask */
211
   false),    /* pcrel_offset */
212
213
  /* A 32 bit absolute relocation  */
214
  HOWTO (R_S12Z_EXT32,        /* type */
215
   0,     /* rightshift */
216
   4,     /* size */
217
   32,      /* bitsize */
218
   false,     /* pc_relative */
219
   0,     /* bitpos */
220
   complain_overflow_bitfield,  /* complain_on_overflow */
221
   bfd_elf_generic_reloc, /* special_function */
222
   "R_S12Z_EXT32",  /* name */
223
   false,     /* partial_inplace */
224
   0x00000000,            /* src_mask */
225
   0xffffffff,    /* dst_mask */
226
   false),    /* pcrel_offset */
227
};
228
229
/* Map BFD reloc types to S12Z ELF reloc types.  */
230
231
struct s12z_reloc_map
232
{
233
  bfd_reloc_code_real_type bfd_reloc_val;
234
  unsigned char elf_reloc_val;
235
};
236
237
static const struct s12z_reloc_map s12z_reloc_map[] =
238
{
239
  /* bfd reloc val */  /* elf reloc val */
240
  {BFD_RELOC_NONE,     R_S12Z_NONE},
241
  {BFD_RELOC_32,       R_S12Z_EXT32},
242
  {BFD_RELOC_24,       R_S12Z_EXT24},
243
  {BFD_RELOC_16_PCREL, R_S12Z_PCREL_7_15},
244
  {BFD_RELOC_S12Z_OPR, R_S12Z_OPR}
245
};
246
247
static reloc_howto_type *
248
bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
249
         bfd_reloc_code_real_type code)
250
0
{
251
0
  unsigned int i;
252
253
0
  for (i = 0;
254
0
       i < sizeof (s12z_reloc_map) / sizeof (struct s12z_reloc_map);
255
0
       i++)
256
0
    {
257
0
      if (s12z_reloc_map[i].bfd_reloc_val == code)
258
0
  {
259
0
    return &elf_s12z_howto_table[s12z_reloc_map[i].elf_reloc_val];
260
0
  }
261
0
    }
262
263
0
  printf ("%s:%d Not found type %d\n", __FILE__, __LINE__, code);
264
265
0
  return NULL;
266
0
}
267
268
static reloc_howto_type *
269
bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
270
         const char *r_name)
271
0
{
272
0
  unsigned int i;
273
274
0
  for (i = 0;
275
0
       i < (sizeof (elf_s12z_howto_table)
276
0
      / sizeof (elf_s12z_howto_table[0]));
277
0
       i++)
278
0
    if (elf_s12z_howto_table[i].name != NULL
279
0
  && strcasecmp (elf_s12z_howto_table[i].name, r_name) == 0)
280
0
      return &elf_s12z_howto_table[i];
281
282
0
  return NULL;
283
0
}
284
285
/* Set the howto pointer for an S12Z ELF reloc.  */
286
287
static bool
288
s12z_info_to_howto_rel (bfd *abfd,
289
        arelent *cache_ptr, Elf_Internal_Rela *dst)
290
0
{
291
0
  unsigned int  r_type = ELF32_R_TYPE (dst->r_info);
292
293
0
  if (r_type >= (unsigned int) R_S12Z_max)
294
0
    {
295
      /* xgettext:c-format */
296
0
      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
297
0
        abfd, r_type);
298
0
      bfd_set_error (bfd_error_bad_value);
299
0
      return false;
300
0
    }
301
302
0
  cache_ptr->howto = &elf_s12z_howto_table[r_type];
303
0
  return true;
304
0
}
305
306
static bool
307
s12z_elf_set_mach_from_flags (bfd *abfd)
308
3
{
309
3
  bfd_default_set_arch_mach (abfd, bfd_arch_s12z, 0);
310
311
3
  return true;
312
3
}
313
314
#define ELF_ARCH    bfd_arch_s12z
315
#define ELF_MACHINE_CODE  EM_S12Z
316
#define ELF_MAXPAGESIZE   0x1000
317
318
#define TARGET_BIG_SYM    s12z_elf32_vec
319
#define TARGET_BIG_NAME   "elf32-s12z"
320
321
#define elf_info_to_howto     NULL
322
#define elf_info_to_howto_rel     s12z_info_to_howto_rel
323
#define elf_backend_object_p      s12z_elf_set_mach_from_flags
324
325
#include "elf32-target.h"