source: trunk/src/binutils/bfd/elf32-pj.c@ 657

Last change on this file since 657 was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 10.9 KB
Line 
1/* picoJava specific support for 32-bit ELF
2 Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Steve Chamberlan of Transmeta (sac@pobox.com).
4
5This file is part of BFD, the Binary File Descriptor library.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
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
28static bfd_reloc_status_type pj_elf_reloc
29 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
30static reloc_howto_type *pj_elf_reloc_type_lookup
31 PARAMS ((bfd *, bfd_reloc_code_real_type));
32static void pj_elf_info_to_howto
33 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
34static void pj_elf_final_write_processing
35 PARAMS ((bfd *, bfd_boolean));
36
37static reloc_howto_type pj_elf_howto_table[] =
38{
39 /* No relocation. */
40 HOWTO (R_PJ_NONE, /* type */
41 0, /* rightshift */
42 0, /* size (0 = byte, 1 = short, 2 = long) */
43 0, /* bitsize */
44 FALSE, /* pc_relative */
45 0, /* bitpos */
46 complain_overflow_dont, /* complain_on_overflow */
47 pj_elf_reloc, /* special_function */
48 "R_PJ_NONE", /* name */
49 FALSE, /* partial_inplace */
50 0, /* src_mask */
51 0, /* dst_mask */
52 FALSE), /* pcrel_offset */
53
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 */
57 0, /* rightshift */
58 2, /* size (0 = byte, 1 = short, 2 = long) */
59 32, /* bitsize */
60 FALSE, /* pc_relative */
61 0, /* bitpos */
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 */
69
70 /* 32 bit PC relative relocation. */
71 HOWTO (R_PJ_CODE_REL32, /* type */
72 0, /* rightshift */
73 2, /* size (0 = byte, 1 = short, 2 = long) */
74 32, /* bitsize */
75 TRUE, /* pc_relative */
76 0, /* bitpos */
77 complain_overflow_signed, /* complain_on_overflow */
78 pj_elf_reloc, /* special_function */
79 "R_PJ_REL32", /* name */
80 FALSE, /* partial_inplace */
81 0, /* src_mask */
82 0xffffffff, /* dst_mask */
83 TRUE), /* pcrel_offset */
84
85/* 16 bit PC relative relocation. */
86 HOWTO (R_PJ_CODE_REL16, /* type */
87 0, /* rightshift */
88 1, /* size (0 = byte, 1 = short, 2 = long) */
89 16, /* bitsize */
90 TRUE, /* pc_relative */
91 0, /* bitpos */
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 */
99 EMPTY_HOWTO (4),
100 EMPTY_HOWTO (5),
101 HOWTO (R_PJ_CODE_DIR32, /* type */
102 0, /* rightshift */
103 2, /* size (0 = byte, 1 = short, 2 = long) */
104 32, /* bitsize */
105 FALSE, /* pc_relative */
106 0, /* bitpos */
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 */
114
115 EMPTY_HOWTO (7),
116 EMPTY_HOWTO (8),
117 EMPTY_HOWTO (9),
118 EMPTY_HOWTO (10),
119 EMPTY_HOWTO (11),
120 EMPTY_HOWTO (12),
121
122 HOWTO (R_PJ_CODE_LO16, /* type */
123 0, /* rightshift */
124 1, /* size (0 = byte, 1 = short, 2 = long) */
125 16, /* bitsize */
126 FALSE, /* pc_relative */
127 0, /* bitpos */
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 */
135
136 HOWTO (R_PJ_CODE_HI16, /* type */
137 16, /* rightshift */
138 1, /* size (0 = byte, 1 = short, 2 = long) */
139 16, /* bitsize */
140 FALSE, /* pc_relative */
141 0, /* bitpos */
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 */
149
150 /* GNU extension to record C++ vtable hierarchy */
151 HOWTO (R_PJ_GNU_VTINHERIT, /* type */
152 0, /* rightshift */
153 2, /* size (0 = byte, 1 = short, 2 = long) */
154 0, /* bitsize */
155 FALSE, /* pc_relative */
156 0, /* bitpos */
157 complain_overflow_dont, /* complain_on_overflow */
158 NULL, /* special_function */
159 "R_PJ_GNU_VTINHERIT", /* name */
160 FALSE, /* partial_inplace */
161 0, /* src_mask */
162 0, /* dst_mask */
163 FALSE), /* pcrel_offset */
164
165 /* GNU extension to record C++ vtable member usage */
166 HOWTO (R_PJ_GNU_VTENTRY, /* type */
167 0, /* rightshift */
168 2, /* size (0 = byte, 1 = short, 2 = long) */
169 0, /* bitsize */
170 FALSE, /* pc_relative */
171 0, /* bitpos */
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 */
176 0, /* src_mask */
177 0, /* dst_mask */
178 FALSE), /* pcrel_offset */
179};
180
181/* This function is used for normal relocs. This is like the COFF
182 function, and is almost certainly incorrect for other ELF targets. */
183
184static bfd_reloc_status_type
185pj_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
186 error_message)
187 bfd *abfd;
188 arelent *reloc_entry;
189 asymbol *symbol_in;
190 PTR data;
191 asection *input_section;
192 bfd *output_bfd;
193 char **error_message ATTRIBUTE_UNUSED;
194{
195 unsigned long insn;
196 bfd_vma sym_value;
197 enum elf_pj_reloc_type r_type;
198 bfd_vma addr = reloc_entry->address;
199 bfd_byte *hit_data = addr + (bfd_byte *) data;
200
201 r_type = (enum elf_pj_reloc_type) reloc_entry->howto->type;
202
203 if (output_bfd != NULL)
204 {
205 /* Partial linking--do nothing. */
206 reloc_entry->address += input_section->output_offset;
207 return bfd_reloc_ok;
208 }
209
210 if (symbol_in != NULL
211 && bfd_is_und_section (symbol_in->section))
212 return bfd_reloc_undefined;
213
214 if (bfd_is_com_section (symbol_in->section))
215 sym_value = 0;
216 else
217 sym_value = (symbol_in->value +
218 symbol_in->section->output_section->vma +
219 symbol_in->section->output_offset);
220
221 switch (r_type)
222 {
223 case R_PJ_DATA_DIR32:
224 insn = bfd_get_32 (abfd, hit_data);
225 insn += sym_value + reloc_entry->addend;
226 bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
227 break;
228
229 /* Relocations in code are always bigendian, no matter what the
230 data endianness is. */
231
232 case R_PJ_CODE_DIR32:
233 insn = bfd_getb32 (hit_data);
234 insn += sym_value + reloc_entry->addend;
235 bfd_putb32 ((bfd_vma) insn, hit_data);
236 break;
237
238 case R_PJ_CODE_REL16:
239 insn = bfd_getb16 (hit_data);
240 insn += sym_value + reloc_entry->addend
241 - (input_section->output_section->vma
242 + input_section->output_offset);
243 bfd_putb16 ((bfd_vma) insn, hit_data);
244 break;
245 case R_PJ_CODE_LO16:
246 insn = bfd_getb16 (hit_data);
247 insn += sym_value + reloc_entry->addend;
248 bfd_putb16 ((bfd_vma) insn, hit_data);
249 break;
250
251 case R_PJ_CODE_HI16:
252 insn = bfd_getb16 (hit_data);
253 insn += (sym_value + reloc_entry->addend) >> 16;
254 bfd_putb16 ((bfd_vma) insn, hit_data);
255 break;
256
257 default:
258 abort ();
259 break;
260 }
261
262 return bfd_reloc_ok;
263}
264
265/* This structure is used to map BFD reloc codes to PJ ELF relocs. */
266
267struct elf_reloc_map
268{
269 bfd_reloc_code_real_type bfd_reloc_val;
270 unsigned char elf_reloc_val;
271};
272
273/* An array mapping BFD reloc codes to PJ ELF relocs. */
274
275static const struct elf_reloc_map pj_reloc_map[] =
276{
277 { BFD_RELOC_NONE, R_PJ_NONE },
278 { BFD_RELOC_32, R_PJ_DATA_DIR32 },
279 { BFD_RELOC_PJ_CODE_DIR16, R_PJ_CODE_DIR16 },
280 { BFD_RELOC_PJ_CODE_DIR32, R_PJ_CODE_DIR32 },
281 { BFD_RELOC_PJ_CODE_LO16, R_PJ_CODE_LO16 },
282 { BFD_RELOC_PJ_CODE_HI16, R_PJ_CODE_HI16 },
283 { BFD_RELOC_PJ_CODE_REL32, R_PJ_CODE_REL32 },
284 { BFD_RELOC_PJ_CODE_REL16, R_PJ_CODE_REL16 },
285 { BFD_RELOC_VTABLE_INHERIT, R_PJ_GNU_VTINHERIT },
286 { BFD_RELOC_VTABLE_ENTRY, R_PJ_GNU_VTENTRY },
287};
288
289/* Given a BFD reloc code, return the howto structure for the
290 corresponding PJ ELf reloc. */
291
292static reloc_howto_type *
293pj_elf_reloc_type_lookup (abfd, code)
294 bfd *abfd ATTRIBUTE_UNUSED;
295 bfd_reloc_code_real_type code;
296{
297 unsigned int i;
298
299 for (i = 0; i < sizeof (pj_reloc_map) / sizeof (struct elf_reloc_map); i++)
300 {
301 if (pj_reloc_map[i].bfd_reloc_val == code)
302 return &pj_elf_howto_table[(int) pj_reloc_map[i].elf_reloc_val];
303 }
304
305 return NULL;
306}
307
308/* Given an ELF reloc, fill in the howto field of a relent. */
309
310static void
311pj_elf_info_to_howto (abfd, cache_ptr, dst)
312 bfd *abfd ATTRIBUTE_UNUSED;
313 arelent *cache_ptr;
314 Elf_Internal_Rela *dst;
315{
316 unsigned int r;
317
318 r = ELF32_R_TYPE (dst->r_info);
319
320 BFD_ASSERT (r < (unsigned int) R_PJ_max);
321
322 cache_ptr->howto = &pj_elf_howto_table[r];
323}
324
325/* Take this moment to fill in the special picoJava bits in the
326 e_flags field. */
327
328static void
329pj_elf_final_write_processing (abfd, linker)
330 bfd *abfd;
331 bfd_boolean linker ATTRIBUTE_UNUSED;
332{
333 elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_ARCH;
334 elf_elfheader (abfd)->e_flags |= EF_PICOJAVA_GNUCALLS;
335}
336
337#define TARGET_BIG_SYM bfd_elf32_pj_vec
338#define TARGET_BIG_NAME "elf32-pj"
339#define TARGET_LITTLE_SYM bfd_elf32_pjl_vec
340#define TARGET_LITTLE_NAME "elf32-pjl"
341#define ELF_ARCH bfd_arch_pj
342#define ELF_MACHINE_CODE EM_PJ
343#define ELF_MACHINE_ALT1 EM_PJ_OLD
344#define ELF_MAXPAGESIZE 0x1000
345#define bfd_elf32_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
346#define bfd_elf32_bfd_reloc_type_lookup pj_elf_reloc_type_lookup
347#define elf_backend_final_write_processing pj_elf_final_write_processing
348#define elf_info_to_howto pj_elf_info_to_howto
349#include "elf32-target.h"
Note: See TracBrowser for help on using the repository browser.