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