Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/bfd/elf32-pj.c
Line
Count
Source (jump to first uncovered line)
1
/* picoJava specific support for 32-bit ELF
2
   Copyright (C) 1999-2025 Free Software Foundation, Inc.
3
   Contributed by Steve Chamberlan of Transmeta (sac@pobox.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/pj.h"
28
29
/* This function is used for normal relocs.  This is like the COFF
30
   function, and is almost certainly incorrect for other ELF targets.  */
31
32
static bfd_reloc_status_type
33
pj_elf_reloc (bfd *abfd,
34
        arelent *reloc_entry,
35
        asymbol *symbol_in,
36
        void * data,
37
        asection *input_section,
38
        bfd *output_bfd,
39
        char **error_message ATTRIBUTE_UNUSED)
40
0
{
41
0
  unsigned long insn;
42
0
  bfd_vma sym_value;
43
0
  enum elf_pj_reloc_type r_type;
44
0
  bfd_vma addr = reloc_entry->address;
45
0
  bfd_byte *hit_data = addr + (bfd_byte *) data;
46
47
0
  r_type = (enum elf_pj_reloc_type) reloc_entry->howto->type;
48
49
0
  if (output_bfd != NULL)
50
0
    {
51
      /* Partial linking--do nothing.  */
52
0
      reloc_entry->address += input_section->output_offset;
53
0
      return bfd_reloc_ok;
54
0
    }
55
56
0
  if (symbol_in != NULL
57
0
      && (symbol_in->flags & BSF_WEAK) == 0
58
0
      && bfd_is_und_section (symbol_in->section))
59
0
    return bfd_reloc_undefined;
60
61
0
  if (bfd_is_com_section (symbol_in->section))
62
0
    sym_value = 0;
63
0
  else
64
0
    sym_value = (symbol_in->value +
65
0
     symbol_in->section->output_section->vma +
66
0
     symbol_in->section->output_offset);
67
68
0
  switch (r_type)
69
0
    {
70
0
    case R_PJ_DATA_DIR32:
71
0
      insn = bfd_get_32 (abfd, hit_data);
72
0
      insn += sym_value + reloc_entry->addend;
73
0
      bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
74
0
      break;
75
76
      /* Relocations in code are always bigendian, no matter what the
77
   data endianness is.  */
78
79
0
    case R_PJ_CODE_DIR32:
80
0
      insn = bfd_getb32 (hit_data);
81
0
      insn += sym_value + reloc_entry->addend;
82
0
      bfd_putb32 ((bfd_vma) insn, hit_data);
83
0
      break;
84
85
0
    case R_PJ_CODE_REL16:
86
0
      insn = bfd_getb16 (hit_data);
87
0
      insn += sym_value + reloc_entry->addend
88
0
  -  (input_section->output_section->vma
89
0
      + input_section->output_offset);
90
0
      bfd_putb16 ((bfd_vma) insn, hit_data);
91
0
      break;
92
0
    case R_PJ_CODE_LO16:
93
0
      insn = bfd_getb16 (hit_data);
94
0
      insn += sym_value + reloc_entry->addend;
95
0
      bfd_putb16 ((bfd_vma) insn, hit_data);
96
0
      break;
97
98
0
    case R_PJ_CODE_HI16:
99
0
      insn = bfd_getb16 (hit_data);
100
0
      insn += (sym_value + reloc_entry->addend) >> 16;
101
0
      bfd_putb16 ((bfd_vma) insn, hit_data);
102
0
      break;
103
104
0
    default:
105
0
      abort ();
106
0
      break;
107
0
    }
108
109
0
  return bfd_reloc_ok;
110
0
}
111
112
static reloc_howto_type pj_elf_howto_table[] =
113
{
114
  /* No relocation.  */
115
  HOWTO (R_PJ_NONE,   /* type */
116
   0,     /* rightshift */
117
   0,     /* size */
118
   0,     /* bitsize */
119
   false,     /* pc_relative */
120
   0,     /* bitpos */
121
   complain_overflow_dont, /* complain_on_overflow */
122
   pj_elf_reloc,    /* special_function */
123
   "R_PJ_NONE",   /* name */
124
   false,     /* partial_inplace */
125
   0,     /* src_mask */
126
   0,     /* dst_mask */
127
   false),    /* pcrel_offset */
128
129
  /* 32 bit absolute relocation.  Setting partial_inplace to TRUE and
130
     src_mask to a non-zero value is similar to the COFF toolchain.  */
131
  HOWTO (R_PJ_DATA_DIR32, /* type */
132
   0,     /* rightshift */
133
   4,     /* size */
134
   32,      /* bitsize */
135
   false,     /* pc_relative */
136
   0,     /* bitpos */
137
   complain_overflow_bitfield, /* complain_on_overflow */
138
   pj_elf_reloc,    /* special_function */
139
   "R_PJ_DIR32",    /* name */
140
   true,      /* partial_inplace */
141
   0xffffffff,    /* src_mask */
142
   0xffffffff,    /* dst_mask */
143
   false),    /* pcrel_offset */
144
145
  /* 32 bit PC relative relocation.  */
146
  HOWTO (R_PJ_CODE_REL32, /* type */
147
   0,     /* rightshift */
148
   4,     /* size */
149
   32,      /* bitsize */
150
   true,      /* pc_relative */
151
   0,     /* bitpos */
152
   complain_overflow_signed, /* complain_on_overflow */
153
   pj_elf_reloc,    /* special_function */
154
   "R_PJ_REL32",    /* name */
155
   false,     /* partial_inplace */
156
   0,     /* src_mask */
157
   0xffffffff,    /* dst_mask */
158
   true),     /* pcrel_offset */
159
160
/* 16 bit PC relative relocation.  */
161
  HOWTO (R_PJ_CODE_REL16, /* type */
162
   0,     /* rightshift */
163
   2,     /* size */
164
   16,      /* bitsize */
165
   true,      /* pc_relative */
166
   0,     /* bitpos */
167
   complain_overflow_signed, /* complain_on_overf6w */
168
   pj_elf_reloc,    /* special_function */
169
   "R_PJ_REL16",    /* name */
170
   false,     /* partial_inplace */
171
   0xffff,    /* src_mask */
172
   0xffff,    /* dst_mask */
173
   true),     /* pcrel_offset */
174
  EMPTY_HOWTO (4),
175
  EMPTY_HOWTO (5),
176
  HOWTO (R_PJ_CODE_DIR32, /* type */
177
   0,     /* rightshift */
178
   4,     /* size */
179
   32,      /* bitsize */
180
   false,     /* pc_relative */
181
   0,     /* bitpos */
182
   complain_overflow_bitfield, /* complain_on_overflow */
183
   pj_elf_reloc,    /* special_function */
184
   "R_PJ_CODE_DIR32", /* name */
185
   true,      /* partial_inplace */
186
   0xffffffff,    /* src_mask */
187
   0xffffffff,    /* dst_mask */
188
   false),    /* pcrel_offset */
189
190
  EMPTY_HOWTO (7),
191
  EMPTY_HOWTO (8),
192
  EMPTY_HOWTO (9),
193
  EMPTY_HOWTO (10),
194
  EMPTY_HOWTO (11),
195
  EMPTY_HOWTO (12),
196
197
  HOWTO (R_PJ_CODE_LO16,  /* type */
198
   0,     /* rightshift */
199
   2,     /* size */
200
   16,      /* bitsize */
201
   false,     /* pc_relative */
202
   0,     /* bitpos */
203
   complain_overflow_unsigned, /* complain_on_overflow */
204
   pj_elf_reloc,    /* special_function */
205
   "R_PJ_LO16",   /* name */
206
   false,     /* partial_inplace */
207
   0xffff,    /* src_mask */
208
   0xffff,    /* dst_mask */
209
   true),     /* pcrel_offset */
210
211
    HOWTO (R_PJ_CODE_HI16,  /* type */
212
   16,      /* rightshift */
213
   2,     /* size */
214
   16,      /* bitsize */
215
   false,     /* pc_relative */
216
   0,     /* bitpos */
217
   complain_overflow_unsigned, /* complain_on_overflow */
218
   pj_elf_reloc,    /* special_function */
219
   "R_PJ_HI16",   /* name */
220
   false,     /* partial_inplace */
221
   0xffff,    /* src_mask */
222
   0xffff,    /* dst_mask */
223
   true),     /* pcrel_offset */
224
225
  /* GNU extension to record C++ vtable hierarchy.  */
226
  HOWTO (R_PJ_GNU_VTINHERIT,  /* type */
227
   0,     /* rightshift */
228
   4,     /* size */
229
   0,     /* bitsize */
230
   false,     /* pc_relative */
231
   0,     /* bitpos */
232
   complain_overflow_dont, /* complain_on_overflow */
233
   NULL,      /* special_function */
234
   "R_PJ_GNU_VTINHERIT",  /* name */
235
   false,     /* partial_inplace */
236
   0,     /* src_mask */
237
   0,     /* dst_mask */
238
   false),    /* pcrel_offset */
239
240
  /* GNU extension to record C++ vtable member usage.  */
241
  HOWTO (R_PJ_GNU_VTENTRY,     /* type */
242
   0,     /* rightshift */
243
   4,     /* size */
244
   0,     /* bitsize */
245
   false,     /* pc_relative */
246
   0,     /* bitpos */
247
   complain_overflow_dont, /* complain_on_overflow */
248
   _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
249
   "R_PJ_GNU_VTENTRY",   /* name */
250
   false,     /* partial_inplace */
251
   0,     /* src_mask */
252
   0,     /* dst_mask */
253
   false),    /* pcrel_offset */
254
};
255
256
/* This structure is used to map BFD reloc codes to PJ ELF relocs.  */
257
258
struct elf_reloc_map
259
{
260
  bfd_reloc_code_real_type bfd_reloc_val;
261
  unsigned char elf_reloc_val;
262
};
263
264
/* An array mapping BFD reloc codes to PJ ELF relocs.  */
265
266
static const struct elf_reloc_map pj_reloc_map[] =
267
{
268
    { BFD_RELOC_NONE,   R_PJ_NONE    },
269
    { BFD_RELOC_32,   R_PJ_DATA_DIR32    },
270
    { BFD_RELOC_PJ_CODE_DIR16,  R_PJ_CODE_DIR16    },
271
    { BFD_RELOC_PJ_CODE_DIR32,  R_PJ_CODE_DIR32    },
272
    { BFD_RELOC_PJ_CODE_LO16, R_PJ_CODE_LO16     },
273
    { BFD_RELOC_PJ_CODE_HI16, R_PJ_CODE_HI16     },
274
    { BFD_RELOC_PJ_CODE_REL32,  R_PJ_CODE_REL32    },
275
    { BFD_RELOC_PJ_CODE_REL16,  R_PJ_CODE_REL16    },
276
    { BFD_RELOC_VTABLE_INHERIT, R_PJ_GNU_VTINHERIT },
277
    { BFD_RELOC_VTABLE_ENTRY,   R_PJ_GNU_VTENTRY   },
278
};
279
280
/* Given a BFD reloc code, return the howto structure for the
281
   corresponding PJ ELf reloc.  */
282
283
static reloc_howto_type *
284
pj_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
285
        bfd_reloc_code_real_type code)
286
0
{
287
0
  unsigned int i;
288
289
0
  for (i = 0; i < sizeof (pj_reloc_map) / sizeof (struct elf_reloc_map); i++)
290
0
    if (pj_reloc_map[i].bfd_reloc_val == code)
291
0
      return & pj_elf_howto_table[(int) pj_reloc_map[i].elf_reloc_val];
292
293
0
  return NULL;
294
0
}
295
296
static reloc_howto_type *
297
pj_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
298
        const char *r_name)
299
0
{
300
0
  unsigned int i;
301
302
0
  for (i = 0;
303
0
       i < sizeof (pj_elf_howto_table) / sizeof (pj_elf_howto_table[0]);
304
0
       i++)
305
0
    if (pj_elf_howto_table[i].name != NULL
306
0
  && strcasecmp (pj_elf_howto_table[i].name, r_name) == 0)
307
0
      return &pj_elf_howto_table[i];
308
309
0
  return NULL;
310
0
}
311
312
/* Given an ELF reloc, fill in the howto field of a relent.  */
313
314
static bool
315
pj_elf_info_to_howto (bfd *abfd,
316
          arelent *cache_ptr,
317
          Elf_Internal_Rela *dst)
318
0
{
319
0
  unsigned int r;
320
321
0
  r = ELF32_R_TYPE (dst->r_info);
322
323
0
  if (r >= R_PJ_max)
324
0
    {
325
      /* xgettext:c-format */
326
0
      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
327
0
        abfd, r);
328
0
      bfd_set_error (bfd_error_bad_value);
329
0
      return false;
330
0
    }
331
332
0
  cache_ptr->howto = &pj_elf_howto_table[r];
333
0
  return true;
334
0
}
335
336
/* Take this moment to fill in the special picoJava bits in the
337
   e_flags field.  */
338
339
static bool
340
pj_elf_final_write_processing (bfd *abfd)
341
0
{
342
0
  elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_ARCH;
343
0
  elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_GNUCALLS;
344
0
  return _bfd_elf_final_write_processing (abfd);
345
0
}
346
347
#define TARGET_BIG_SYM    pj_elf32_vec
348
#define TARGET_BIG_NAME   "elf32-pj"
349
#define TARGET_LITTLE_SYM pj_elf32_le_vec
350
#define TARGET_LITTLE_NAME  "elf32-pjl"
351
#define ELF_ARCH    bfd_arch_pj
352
#define ELF_MACHINE_CODE  EM_PJ
353
#define ELF_MACHINE_ALT1  EM_PJ_OLD
354
#define ELF_MAXPAGESIZE   0x1000
355
#define bfd_elf32_bfd_get_relocated_section_contents \
356
  bfd_generic_get_relocated_section_contents
357
#define bfd_elf32_bfd_reloc_type_lookup   pj_elf_reloc_type_lookup
358
#define bfd_elf32_bfd_reloc_name_lookup   pj_elf_reloc_name_lookup
359
#define elf_backend_final_write_processing      pj_elf_final_write_processing
360
#define elf_info_to_howto     pj_elf_info_to_howto
361
#include "elf32-target.h"