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