1
/* picoJava specific support for 32-bit ELF
2
Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
3
Contributed by Steve Chamberlan of Transmeta (sac@pobox.com).
5
This file is part of BFD, the Binary File Descriptor library.
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 2 of the License, or
10
(at your option) any later version.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
28
static bfd_reloc_status_type pj_elf_reloc
29
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
30
static reloc_howto_type *pj_elf_reloc_type_lookup
31
PARAMS ((bfd *, bfd_reloc_code_real_type));
32
static void pj_elf_info_to_howto
33
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
34
static void pj_elf_final_write_processing
35
PARAMS ((bfd *, boolean));
37
static reloc_howto_type pj_elf_howto_table[] =
40
HOWTO (R_PJ_NONE, /* type */
42
0, /* size (0 = byte, 1 = short, 2 = long) */
44
false, /* pc_relative */
46
complain_overflow_dont, /* complain_on_overflow */
47
pj_elf_reloc, /* special_function */
48
"R_PJ_NONE", /* name */
49
false, /* partial_inplace */
52
false), /* pcrel_offset */
54
/* 32 bit absolute relocation. Setting partial_inplace to true and
55
src_mask to a non-zero value is similar to the COFF toolchain. */
56
HOWTO (R_PJ_DATA_DIR32, /* type */
58
2, /* size (0 = byte, 1 = short, 2 = long) */
60
false, /* pc_relative */
62
complain_overflow_bitfield, /* complain_on_overflow */
63
pj_elf_reloc, /* special_function */
64
"R_PJ_DIR32", /* name */
65
true, /* partial_inplace */
66
0xffffffff, /* src_mask */
67
0xffffffff, /* dst_mask */
68
false), /* pcrel_offset */
70
/* 32 bit PC relative relocation. */
71
HOWTO (R_PJ_CODE_REL32, /* type */
73
2, /* size (0 = byte, 1 = short, 2 = long) */
75
true, /* pc_relative */
77
complain_overflow_signed, /* complain_on_overflow */
78
pj_elf_reloc, /* special_function */
79
"R_PJ_REL32", /* name */
80
false, /* partial_inplace */
82
0xffffffff, /* dst_mask */
83
true), /* pcrel_offset */
85
/* 16 bit PC relative relocation. */
86
HOWTO (R_PJ_CODE_REL16, /* type */
88
1, /* size (0 = byte, 1 = short, 2 = long) */
90
true, /* pc_relative */
92
complain_overflow_signed, /* complain_on_overf6w */
93
pj_elf_reloc, /* special_function */
94
"R_PJ_REL16", /* name */
95
false, /* partial_inplace */
96
0xffff, /* src_mask */
97
0xffff, /* dst_mask */
98
true), /* pcrel_offset */
101
HOWTO (R_PJ_CODE_DIR32, /* type */
103
2, /* size (0 = byte, 1 = short, 2 = long) */
105
false, /* pc_relative */
107
complain_overflow_bitfield, /* complain_on_overflow */
108
pj_elf_reloc, /* special_function */
109
"R_PJ_CODE_DIR32", /* name */
110
true, /* partial_inplace */
111
0xffffffff, /* src_mask */
112
0xffffffff, /* dst_mask */
113
false), /* pcrel_offset */
122
HOWTO (R_PJ_CODE_LO16, /* type */
124
1, /* size (0 = byte, 1 = short, 2 = long) */
126
false, /* pc_relative */
128
complain_overflow_unsigned, /* complain_on_overflow */
129
pj_elf_reloc, /* special_function */
130
"R_PJ_LO16", /* name */
131
false, /* partial_inplace */
132
0xffff, /* src_mask */
133
0xffff, /* dst_mask */
134
true), /* pcrel_offset */
136
HOWTO (R_PJ_CODE_HI16, /* type */
138
1, /* size (0 = byte, 1 = short, 2 = long) */
140
false, /* pc_relative */
142
complain_overflow_unsigned, /* complain_on_overflow */
143
pj_elf_reloc, /* special_function */
144
"R_PJ_HI16", /* name */
145
false, /* partial_inplace */
146
0xffff, /* src_mask */
147
0xffff, /* dst_mask */
148
true), /* pcrel_offset */
150
/* GNU extension to record C++ vtable hierarchy */
151
HOWTO (R_PJ_GNU_VTINHERIT, /* type */
153
2, /* size (0 = byte, 1 = short, 2 = long) */
155
false, /* pc_relative */
157
complain_overflow_dont, /* complain_on_overflow */
158
NULL, /* special_function */
159
"R_PJ_GNU_VTINHERIT", /* name */
160
false, /* partial_inplace */
163
false), /* pcrel_offset */
165
/* GNU extension to record C++ vtable member usage */
166
HOWTO (R_PJ_GNU_VTENTRY, /* type */
168
2, /* size (0 = byte, 1 = short, 2 = long) */
170
false, /* pc_relative */
172
complain_overflow_dont, /* complain_on_overflow */
173
_bfd_elf_rel_vtable_reloc_fn, /* special_function */
174
"R_PJ_GNU_VTENTRY", /* name */
175
false, /* partial_inplace */
178
false), /* pcrel_offset */
182
/* This function is used for normal relocs. This is like the COFF
183
function, and is almost certainly incorrect for other ELF targets. */
185
static bfd_reloc_status_type
186
pj_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
189
arelent *reloc_entry;
192
asection *input_section;
194
char **error_message ATTRIBUTE_UNUSED;
198
enum elf_pj_reloc_type r_type;
199
bfd_vma addr = reloc_entry->address;
200
bfd_byte *hit_data = addr + (bfd_byte *) data;
202
r_type = (enum elf_pj_reloc_type) reloc_entry->howto->type;
204
if (output_bfd != NULL)
206
/* Partial linking--do nothing. */
207
reloc_entry->address += input_section->output_offset;
211
if (symbol_in != NULL
212
&& bfd_is_und_section (symbol_in->section))
213
return bfd_reloc_undefined;
215
if (bfd_is_com_section (symbol_in->section))
218
sym_value = (symbol_in->value +
219
symbol_in->section->output_section->vma +
220
symbol_in->section->output_offset);
224
case R_PJ_DATA_DIR32:
225
insn = bfd_get_32 (abfd, hit_data);
226
insn += sym_value + reloc_entry->addend;
227
bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
230
/* Relocations in code are always bigendian, no matter what the
231
data endianness is. */
233
case R_PJ_CODE_DIR32:
234
insn = bfd_getb32 (hit_data);
235
insn += sym_value + reloc_entry->addend;
236
bfd_putb32 ((bfd_vma) insn, hit_data);
239
case R_PJ_CODE_REL16:
240
insn = bfd_getb16 (hit_data);
241
insn += sym_value + reloc_entry->addend
242
- (input_section->output_section->vma
243
+ input_section->output_offset);
244
bfd_putb16 ((bfd_vma) insn, hit_data);
247
insn = bfd_getb16 (hit_data);
248
insn += sym_value + reloc_entry->addend;
249
bfd_putb16 ((bfd_vma) insn, hit_data);
253
insn = bfd_getb16 (hit_data);
254
insn += (sym_value + reloc_entry->addend) >> 16;
255
bfd_putb16 ((bfd_vma) insn, hit_data);
266
/* This structure is used to map BFD reloc codes to PJ ELF relocs. */
270
bfd_reloc_code_real_type bfd_reloc_val;
271
unsigned char elf_reloc_val;
274
/* An array mapping BFD reloc codes to PJ ELF relocs. */
276
static const struct elf_reloc_map pj_reloc_map[] =
278
{ BFD_RELOC_NONE, R_PJ_NONE },
279
{ BFD_RELOC_32, R_PJ_DATA_DIR32 },
280
{ BFD_RELOC_PJ_CODE_DIR16, R_PJ_CODE_DIR16 },
281
{ BFD_RELOC_PJ_CODE_DIR32, R_PJ_CODE_DIR32 },
282
{ BFD_RELOC_PJ_CODE_LO16, R_PJ_CODE_LO16 },
283
{ BFD_RELOC_PJ_CODE_HI16, R_PJ_CODE_HI16 },
284
{ BFD_RELOC_PJ_CODE_REL32, R_PJ_CODE_REL32 },
285
{ BFD_RELOC_PJ_CODE_REL16, R_PJ_CODE_REL16 },
286
{ BFD_RELOC_VTABLE_INHERIT, R_PJ_GNU_VTINHERIT },
287
{ BFD_RELOC_VTABLE_ENTRY, R_PJ_GNU_VTENTRY },
290
/* Given a BFD reloc code, return the howto structure for the
291
corresponding PJ ELf reloc. */
293
static reloc_howto_type *
294
pj_elf_reloc_type_lookup (abfd, code)
295
bfd *abfd ATTRIBUTE_UNUSED;
296
bfd_reloc_code_real_type code;
300
for (i = 0; i < sizeof (pj_reloc_map) / sizeof (struct elf_reloc_map); i++)
302
if (pj_reloc_map[i].bfd_reloc_val == code)
303
return &pj_elf_howto_table[(int) pj_reloc_map[i].elf_reloc_val];
309
/* Given an ELF reloc, fill in the howto field of a relent. */
312
pj_elf_info_to_howto (abfd, cache_ptr, dst)
313
bfd *abfd ATTRIBUTE_UNUSED;
315
Elf_Internal_Rela *dst;
319
r = ELF32_R_TYPE (dst->r_info);
321
BFD_ASSERT (r < (unsigned int) R_PJ_max);
323
cache_ptr->howto = &pj_elf_howto_table[r];
326
/* Take this moment to fill in the special picoJava bits in the
330
pj_elf_final_write_processing (abfd, linker)
332
boolean linker ATTRIBUTE_UNUSED;
334
elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_ARCH;
335
elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_GNUCALLS;
338
#define TARGET_BIG_SYM bfd_elf32_pj_vec
339
#define TARGET_BIG_NAME "elf32-pj"
340
#define TARGET_LITTLE_SYM bfd_elf32_pjl_vec
341
#define TARGET_LITTLE_NAME "elf32-pjl"
342
#define ELF_ARCH bfd_arch_pj
343
#define ELF_MACHINE_CODE EM_PJ
344
#define ELF_MACHINE_ALT1 EM_PJ_OLD
345
#define ELF_MAXPAGESIZE 0x1000
346
#define bfd_elf32_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
347
#define bfd_elf32_bfd_reloc_type_lookup pj_elf_reloc_type_lookup
348
#define elf_backend_final_write_processing pj_elf_final_write_processing
349
#define elf_info_to_howto pj_elf_info_to_howto
350
#include "elf32-target.h"