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