daily update
[deliverable/binutils-gdb.git] / bfd / elf32-pj.c
CommitLineData
0bcb993b 1/* picoJava specific support for 32-bit ELF
157090f7
AM
2 Copyright 1999, 2000, 2001, 2002, 2005, 2007
3 Free Software Foundation, Inc.
0bcb993b
ILT
4 Contributed by Steve Chamberlan of Transmeta (sac@pobox.com).
5
47b0e7ad 6 This file is part of BFD, the Binary File Descriptor library.
0bcb993b 7
47b0e7ad
NC
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
cd123cb7 10 the Free Software Foundation; either version 3 of the License, or
47b0e7ad 11 (at your option) any later version.
0bcb993b 12
47b0e7ad
NC
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
0bcb993b 17
47b0e7ad
NC
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
cd123cb7
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
0bcb993b 22
0bcb993b 23#include "sysdep.h"
3db64b00 24#include "bfd.h"
0bcb993b
ILT
25#include "bfdlink.h"
26#include "libbfd.h"
27#include "elf-bfd.h"
28#include "elf/pj.h"
29
47b0e7ad
NC
30/* This function is used for normal relocs. This is like the COFF
31 function, and is almost certainly incorrect for other ELF targets. */
32
33static bfd_reloc_status_type
34pj_elf_reloc (bfd *abfd,
35 arelent *reloc_entry,
36 asymbol *symbol_in,
37 void * data,
38 asection *input_section,
39 bfd *output_bfd,
40 char **error_message ATTRIBUTE_UNUSED)
41{
42 unsigned long insn;
43 bfd_vma sym_value;
44 enum elf_pj_reloc_type r_type;
45 bfd_vma addr = reloc_entry->address;
46 bfd_byte *hit_data = addr + (bfd_byte *) data;
47
48 r_type = (enum elf_pj_reloc_type) reloc_entry->howto->type;
49
50 if (output_bfd != NULL)
51 {
52 /* Partial linking--do nothing. */
53 reloc_entry->address += input_section->output_offset;
54 return bfd_reloc_ok;
55 }
56
57 if (symbol_in != NULL
58 && bfd_is_und_section (symbol_in->section))
59 return bfd_reloc_undefined;
60
61 if (bfd_is_com_section (symbol_in->section))
62 sym_value = 0;
63 else
64 sym_value = (symbol_in->value +
65 symbol_in->section->output_section->vma +
66 symbol_in->section->output_offset);
67
68 switch (r_type)
69 {
70 case R_PJ_DATA_DIR32:
71 insn = bfd_get_32 (abfd, hit_data);
72 insn += sym_value + reloc_entry->addend;
73 bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
74 break;
75
76 /* Relocations in code are always bigendian, no matter what the
77 data endianness is. */
78
79 case R_PJ_CODE_DIR32:
80 insn = bfd_getb32 (hit_data);
81 insn += sym_value + reloc_entry->addend;
82 bfd_putb32 ((bfd_vma) insn, hit_data);
83 break;
84
85 case R_PJ_CODE_REL16:
86 insn = bfd_getb16 (hit_data);
87 insn += sym_value + reloc_entry->addend
88 - (input_section->output_section->vma
89 + input_section->output_offset);
90 bfd_putb16 ((bfd_vma) insn, hit_data);
91 break;
92 case R_PJ_CODE_LO16:
93 insn = bfd_getb16 (hit_data);
94 insn += sym_value + reloc_entry->addend;
95 bfd_putb16 ((bfd_vma) insn, hit_data);
96 break;
97
98 case R_PJ_CODE_HI16:
99 insn = bfd_getb16 (hit_data);
100 insn += (sym_value + reloc_entry->addend) >> 16;
101 bfd_putb16 ((bfd_vma) insn, hit_data);
102 break;
103
104 default:
105 abort ();
106 break;
107 }
108
109 return bfd_reloc_ok;
110}
0bcb993b
ILT
111
112static reloc_howto_type pj_elf_howto_table[] =
113{
114 /* No relocation. */
115 HOWTO (R_PJ_NONE, /* type */
116 0, /* rightshift */
117 0, /* size (0 = byte, 1 = short, 2 = long) */
118 0, /* bitsize */
b34976b6 119 FALSE, /* pc_relative */
0bcb993b
ILT
120 0, /* bitpos */
121 complain_overflow_dont, /* complain_on_overflow */
122 pj_elf_reloc, /* special_function */
123 "R_PJ_NONE", /* name */
b34976b6 124 FALSE, /* partial_inplace */
0bcb993b
ILT
125 0, /* src_mask */
126 0, /* dst_mask */
b34976b6 127 FALSE), /* pcrel_offset */
0bcb993b 128
b34976b6 129 /* 32 bit absolute relocation. Setting partial_inplace to TRUE and
0bcb993b 130 src_mask to a non-zero value is similar to the COFF toolchain. */
47b0e7ad 131 HOWTO (R_PJ_DATA_DIR32, /* type */
0bcb993b
ILT
132 0, /* rightshift */
133 2, /* size (0 = byte, 1 = short, 2 = long) */
134 32, /* bitsize */
b34976b6 135 FALSE, /* pc_relative */
0bcb993b
ILT
136 0, /* bitpos */
137 complain_overflow_bitfield, /* complain_on_overflow */
138 pj_elf_reloc, /* special_function */
139 "R_PJ_DIR32", /* name */
b34976b6 140 TRUE, /* partial_inplace */
0bcb993b
ILT
141 0xffffffff, /* src_mask */
142 0xffffffff, /* dst_mask */
b34976b6 143 FALSE), /* pcrel_offset */
0bcb993b
ILT
144
145 /* 32 bit PC relative relocation. */
47b0e7ad 146 HOWTO (R_PJ_CODE_REL32, /* type */
0bcb993b
ILT
147 0, /* rightshift */
148 2, /* size (0 = byte, 1 = short, 2 = long) */
149 32, /* bitsize */
b34976b6 150 TRUE, /* pc_relative */
0bcb993b
ILT
151 0, /* bitpos */
152 complain_overflow_signed, /* complain_on_overflow */
153 pj_elf_reloc, /* special_function */
154 "R_PJ_REL32", /* name */
b34976b6 155 FALSE, /* partial_inplace */
0bcb993b
ILT
156 0, /* src_mask */
157 0xffffffff, /* dst_mask */
b34976b6 158 TRUE), /* pcrel_offset */
0bcb993b
ILT
159
160/* 16 bit PC relative relocation. */
47b0e7ad 161 HOWTO (R_PJ_CODE_REL16, /* type */
0bcb993b
ILT
162 0, /* rightshift */
163 1, /* size (0 = byte, 1 = short, 2 = long) */
164 16, /* bitsize */
b34976b6 165 TRUE, /* pc_relative */
0bcb993b
ILT
166 0, /* bitpos */
167 complain_overflow_signed, /* complain_on_overf6w */
168 pj_elf_reloc, /* special_function */
169 "R_PJ_REL16", /* name */
b34976b6 170 FALSE, /* partial_inplace */
0bcb993b
ILT
171 0xffff, /* src_mask */
172 0xffff, /* dst_mask */
b34976b6 173 TRUE), /* pcrel_offset */
0bcb993b
ILT
174 EMPTY_HOWTO (4),
175 EMPTY_HOWTO (5),
176 HOWTO (R_PJ_CODE_DIR32, /* type */
177 0, /* rightshift */
178 2, /* size (0 = byte, 1 = short, 2 = long) */
179 32, /* bitsize */
b34976b6 180 FALSE, /* pc_relative */
0bcb993b
ILT
181 0, /* bitpos */
182 complain_overflow_bitfield, /* complain_on_overflow */
183 pj_elf_reloc, /* special_function */
184 "R_PJ_CODE_DIR32", /* name */
b34976b6 185 TRUE, /* partial_inplace */
0bcb993b
ILT
186 0xffffffff, /* src_mask */
187 0xffffffff, /* dst_mask */
b34976b6 188 FALSE), /* pcrel_offset */
0bcb993b
ILT
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 1, /* size (0 = byte, 1 = short, 2 = long) */
200 16, /* bitsize */
b34976b6 201 FALSE, /* pc_relative */
0bcb993b
ILT
202 0, /* bitpos */
203 complain_overflow_unsigned, /* complain_on_overflow */
204 pj_elf_reloc, /* special_function */
205 "R_PJ_LO16", /* name */
b34976b6 206 FALSE, /* partial_inplace */
0bcb993b
ILT
207 0xffff, /* src_mask */
208 0xffff, /* dst_mask */
b34976b6 209 TRUE), /* pcrel_offset */
0bcb993b 210
0bcb993b
ILT
211 HOWTO (R_PJ_CODE_HI16, /* type */
212 16, /* rightshift */
213 1, /* size (0 = byte, 1 = short, 2 = long) */
214 16, /* bitsize */
b34976b6 215 FALSE, /* pc_relative */
0bcb993b
ILT
216 0, /* bitpos */
217 complain_overflow_unsigned, /* complain_on_overflow */
218 pj_elf_reloc, /* special_function */
219 "R_PJ_HI16", /* name */
b34976b6 220 FALSE, /* partial_inplace */
0bcb993b
ILT
221 0xffff, /* src_mask */
222 0xffff, /* dst_mask */
b34976b6 223 TRUE), /* pcrel_offset */
0bcb993b 224
47b0e7ad 225 /* GNU extension to record C++ vtable hierarchy. */
0bcb993b
ILT
226 HOWTO (R_PJ_GNU_VTINHERIT, /* type */
227 0, /* rightshift */
228 2, /* size (0 = byte, 1 = short, 2 = long) */
229 0, /* bitsize */
b34976b6 230 FALSE, /* pc_relative */
0bcb993b
ILT
231 0, /* bitpos */
232 complain_overflow_dont, /* complain_on_overflow */
233 NULL, /* special_function */
234 "R_PJ_GNU_VTINHERIT", /* name */
b34976b6 235 FALSE, /* partial_inplace */
0bcb993b
ILT
236 0, /* src_mask */
237 0, /* dst_mask */
b34976b6 238 FALSE), /* pcrel_offset */
0bcb993b 239
47b0e7ad 240 /* GNU extension to record C++ vtable member usage. */
0bcb993b
ILT
241 HOWTO (R_PJ_GNU_VTENTRY, /* type */
242 0, /* rightshift */
243 2, /* size (0 = byte, 1 = short, 2 = long) */
244 0, /* bitsize */
b34976b6 245 FALSE, /* pc_relative */
0bcb993b
ILT
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 */
b34976b6 250 FALSE, /* partial_inplace */
0bcb993b
ILT
251 0, /* src_mask */
252 0, /* dst_mask */
b34976b6 253 FALSE), /* pcrel_offset */
0bcb993b
ILT
254};
255
0bcb993b
ILT
256/* This structure is used to map BFD reloc codes to PJ ELF relocs. */
257
258struct 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
266static 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
283static reloc_howto_type *
47b0e7ad
NC
284pj_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
285 bfd_reloc_code_real_type code)
0bcb993b
ILT
286{
287 unsigned int i;
c3668558 288
0bcb993b 289 for (i = 0; i < sizeof (pj_reloc_map) / sizeof (struct elf_reloc_map); i++)
47b0e7ad
NC
290 if (pj_reloc_map[i].bfd_reloc_val == code)
291 return & pj_elf_howto_table[(int) pj_reloc_map[i].elf_reloc_val];
0bcb993b
ILT
292
293 return NULL;
294}
295
157090f7
AM
296static reloc_howto_type *
297pj_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
298 const char *r_name)
299{
300 unsigned int i;
301
302 for (i = 0;
303 i < sizeof (pj_elf_howto_table) / sizeof (pj_elf_howto_table[0]);
304 i++)
305 if (pj_elf_howto_table[i].name != NULL
306 && strcasecmp (pj_elf_howto_table[i].name, r_name) == 0)
307 return &pj_elf_howto_table[i];
308
309 return NULL;
310}
311
0bcb993b
ILT
312/* Given an ELF reloc, fill in the howto field of a relent. */
313
314static void
47b0e7ad
NC
315pj_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
316 arelent *cache_ptr,
317 Elf_Internal_Rela *dst)
0bcb993b
ILT
318{
319 unsigned int r;
320
321 r = ELF32_R_TYPE (dst->r_info);
322
323 BFD_ASSERT (r < (unsigned int) R_PJ_max);
324
325 cache_ptr->howto = &pj_elf_howto_table[r];
326}
327
328/* Take this moment to fill in the special picoJava bits in the
c3668558 329 e_flags field. */
0bcb993b
ILT
330
331static void
47b0e7ad
NC
332pj_elf_final_write_processing (bfd *abfd,
333 bfd_boolean linker ATTRIBUTE_UNUSED)
0bcb993b 334{
47b0e7ad
NC
335 elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_ARCH;
336 elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_GNUCALLS;
0bcb993b
ILT
337}
338
339#define TARGET_BIG_SYM bfd_elf32_pj_vec
340#define TARGET_BIG_NAME "elf32-pj"
341#define TARGET_LITTLE_SYM bfd_elf32_pjl_vec
342#define TARGET_LITTLE_NAME "elf32-pjl"
343#define ELF_ARCH bfd_arch_pj
344#define ELF_MACHINE_CODE EM_PJ
aa4f99bb 345#define ELF_MACHINE_ALT1 EM_PJ_OLD
0bcb993b 346#define ELF_MAXPAGESIZE 0x1000
157090f7
AM
347#define bfd_elf32_bfd_get_relocated_section_contents \
348 bfd_generic_get_relocated_section_contents
349#define bfd_elf32_bfd_reloc_type_lookup pj_elf_reloc_type_lookup
350#define bfd_elf32_bfd_reloc_name_lookup pj_elf_reloc_name_lookup
351#define elf_backend_final_write_processing pj_elf_final_write_processing
352#define elf_info_to_howto pj_elf_info_to_howto
0bcb993b 353#include "elf32-target.h"
This page took 0.479992 seconds and 4 git commands to generate.