Coverage Report

Created: 2026-07-25 10:20

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