This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/binutils-gdb.git] / bfd / elf32-d30v.c
1 /* D30V-specific support for 32-bit ELF
2 Copyright (C) 1997 Free Software Foundation, Inc.
3 Contributed by Martin Hunt (hunt@cygnus.com).
4
5 This file is part of BFD, the Binary File Descriptor library.
6
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.
11
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.
16
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. */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "elf-bfd.h"
25
26 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
27 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
28 static void d30v_info_to_howto_rel
29 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
30 static bfd_reloc_status_type bfd_elf_d30v_reloc PARAMS ((
31 bfd *abfd,
32 arelent *reloc_entry,
33 asymbol *symbol,
34 PTR data,
35 asection *input_section,
36 bfd *output_bfd,
37 char **error_message));
38
39 /* Use REL instead of RELA to save space */
40 #define USE_REL
41
42 enum reloc_type
43 {
44 R_D30V_NONE = 0,
45 R_D30V_6,
46 R_D30V_15,
47 R_D30V_15_PCREL,
48 R_D30V_21,
49 R_D30V_21_PCREL,
50 R_D30V_32,
51 R_D30V_32_PCREL,
52 R_D30V_32_NORMAL,
53 R_D30V_max
54 };
55
56 static reloc_howto_type elf_d30v_howto_table[] =
57 {
58 /* This reloc does nothing. */
59 HOWTO (R_D30V_NONE, /* type */
60 0, /* rightshift */
61 2, /* size (0 = byte, 1 = short, 2 = long) */
62 32, /* bitsize */
63 false, /* pc_relative */
64 0, /* bitpos */
65 complain_overflow_bitfield, /* complain_on_overflow */
66 bfd_elf_generic_reloc, /* special_function */
67 "R_D30V_NONE", /* name */
68 false, /* partial_inplace */
69 0, /* src_mask */
70 0, /* dst_mask */
71 false), /* pcrel_offset */
72
73 /* A 6 bit absolute relocation */
74 HOWTO (R_D30V_6, /* type */
75 0, /* rightshift */
76 2, /* size (0 = byte, 1 = short, 2 = long) */
77 6, /* bitsize */
78 false, /* pc_relative */
79 0, /* bitpos */
80 complain_overflow_bitfield, /* complain_on_overflow */
81 bfd_elf_generic_reloc, /* special_function */
82 "R_D30V_6", /* name */
83 false, /* partial_inplace */
84 0x3f, /* src_mask */
85 0x3f, /* dst_mask */
86 false), /* pcrel_offset */
87
88 /* An absolute 15 bit relocation, right shifted by 3 */
89 HOWTO (R_D30V_15, /* type */
90 3, /* rightshift */
91 2, /* size (0 = byte, 1 = short, 2 = long) */
92 15, /* bitsize */
93 false, /* pc_relative */
94 0, /* bitpos */
95 complain_overflow_signed, /* complain_on_overflow */
96 bfd_elf_generic_reloc, /* special_function */
97 "R_D30V_15", /* name */
98 false, /* partial_inplace */
99 0xfff, /* src_mask */
100 0xfff, /* dst_mask */
101 false), /* pcrel_offset */
102
103 /* A relative 15 bit relocation, right shifted by 3 */
104 HOWTO (R_D30V_15_PCREL, /* type */
105 3, /* rightshift */
106 2, /* size (0 = byte, 1 = short, 2 = long) */
107 15, /* bitsize */
108 true, /* pc_relative */
109 0, /* bitpos */
110 complain_overflow_signed, /* complain_on_overflow */
111 bfd_elf_generic_reloc, /* special_function */
112 "R_D30V_15_PCREL", /* name */
113 false, /* partial_inplace */
114 0xfff, /* src_mask */
115 0xfff, /* dst_mask */
116 true), /* pcrel_offset */
117
118 /* An absolute 21 bit relocation, right shifted by 3 */
119 HOWTO (R_D30V_21_PCREL, /* type */
120 3, /* rightshift */
121 2, /* size (0 = byte, 1 = short, 2 = long) */
122 21, /* bitsize */
123 false, /* pc_relative */
124 0, /* bitpos */
125 complain_overflow_signed, /* complain_on_overflow */
126 bfd_elf_generic_reloc, /* special_function */
127 "R_D30V_21", /* name */
128 false, /* partial_inplace */
129 0x3ffff, /* src_mask */
130 0x3ffff, /* dst_mask */
131 false), /* pcrel_offset */
132
133 /* A relative 21 bit relocation, right shifted by 3 */
134 HOWTO (R_D30V_21_PCREL, /* type */
135 3, /* rightshift */
136 2, /* size (0 = byte, 1 = short, 2 = long) */
137 21, /* bitsize */
138 true, /* pc_relative */
139 0, /* bitpos */
140 complain_overflow_signed, /* complain_on_overflow */
141 bfd_elf_generic_reloc, /* special_function */
142 "R_D30V_21_PCREL", /* name */
143 false, /* partial_inplace */
144 0x3ffff, /* src_mask */
145 0x3ffff, /* dst_mask */
146 true), /* pcrel_offset */
147
148 /* A D30V 32 bit absolute relocation */
149 HOWTO (R_D30V_32, /* type */
150 0, /* rightshift */
151 4, /* size (0 = byte, 1 = short, 2 = long) */
152 32, /* bitsize */
153 false, /* pc_relative */
154 0, /* bitpos */
155 complain_overflow_bitfield, /* complain_on_overflow */
156 bfd_elf_d30v_reloc, /* special_function */
157 "R_D30V_32", /* name */
158 false, /* partial_inplace */
159 0xffffffff, /* src_mask */
160 0xffffffff, /* dst_mask */
161 false), /* pcrel_offset */
162
163 /* A relative 32 bit relocation */
164 HOWTO (R_D30V_32_PCREL, /* type */
165 0, /* rightshift */
166 4, /* size (0 = byte, 1 = short, 2 = long) */
167 32, /* bitsize */
168 true, /* pc_relative */
169 0, /* bitpos */
170 complain_overflow_signed, /* complain_on_overflow */
171 bfd_elf_d30v_reloc, /* special_function */
172 "R_D30V_32_PCREL", /* name */
173 false, /* partial_inplace */
174 0xffffffff, /* src_mask */
175 0xffffffff, /* dst_mask */
176 true), /* pcrel_offset */
177
178 /* A regular 32 bit absolute relocation */
179 HOWTO (R_D30V_32_NORMAL, /* type */
180 0, /* rightshift */
181 4, /* size (0 = byte, 1 = short, 2 = long) */
182 32, /* bitsize */
183 false, /* pc_relative */
184 0, /* bitpos */
185 complain_overflow_bitfield, /* complain_on_overflow */
186 bfd_elf_generic_reloc, /* special_function */
187 "R_D30V_32_NORMAL", /* name */
188 false, /* partial_inplace */
189 0xffffffff, /* src_mask */
190 0xffffffff, /* dst_mask */
191 false), /* pcrel_offset */
192
193 };
194
195 static bfd_reloc_status_type
196 bfd_elf_d30v_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message)
197 bfd *abfd;
198 arelent *reloc_entry;
199 asymbol *symbol;
200 PTR data;
201 asection *input_section;
202 bfd *output_bfd;
203 char **error_message;
204 {
205 bfd_vma relocation;
206 bfd_vma in1, in2;
207 bfd_reloc_status_type r;
208 asection *reloc_target_output_section;
209 bfd_size_type addr = reloc_entry->address;
210 bfd_reloc_status_type flag = bfd_reloc_ok;
211 bfd_vma output_base = 0;
212 reloc_howto_type *howto = reloc_entry->howto;
213
214 r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
215 input_section, output_bfd, error_message);
216 if (r != bfd_reloc_continue)
217 return r;
218
219 /* a hacked-up version of bfd_perform_reloc() follows */
220
221 /* Is the address of the relocation really within the section? */
222 if (reloc_entry->address > input_section->_cooked_size)
223 return bfd_reloc_outofrange;
224
225 /* Work out which section the relocation is targetted at and the
226 initial relocation command value. */
227
228 /* Get symbol value. (Common symbols are special.) */
229 if (bfd_is_com_section (symbol->section))
230 relocation = 0;
231 else
232 relocation = symbol->value;
233
234
235 reloc_target_output_section = symbol->section->output_section;
236
237 /* Convert input-section-relative symbol value to absolute. */
238 if (output_bfd)
239 output_base = 0;
240 else
241 output_base = reloc_target_output_section->vma;
242
243 relocation += output_base + symbol->section->output_offset;
244
245 /* Add in supplied addend. */
246 relocation += reloc_entry->addend;
247
248 /* Here the variable relocation holds the final address of the
249 symbol we are relocating against, plus any addend. */
250
251 if (howto->pc_relative == true)
252 {
253 relocation -= input_section->output_section->vma + input_section->output_offset;
254
255 if (howto->pcrel_offset == true)
256 relocation -= reloc_entry->address;
257 }
258
259 if (output_bfd != (bfd *) NULL)
260 {
261 /* This is a partial relocation, and we want to apply the relocation
262 to the reloc entry rather than the raw data. Modify the reloc
263 inplace to reflect what we now know. */
264 reloc_entry->addend = relocation;
265 reloc_entry->address += input_section->output_offset;
266 return flag;
267 }
268 else
269 reloc_entry->addend = 0;
270
271 in1 = bfd_get_32 (abfd, (bfd_byte *) data + addr);
272 in2 = bfd_get_32 (abfd, (bfd_byte *) data + addr + 4);
273
274 printf("D30V 32-bit reloc at addr 0x%lx insn=0x%08x%08x\n",(long)relocation, (int)in1, (int)in2);
275 bfd_put_32 (abfd, in1, (bfd_byte *) data + addr);
276 bfd_put_32 (abfd, in2, (bfd_byte *) data + addr + 4);
277
278 return flag;
279 }
280
281 /* Map BFD reloc types to D30V ELF reloc types. */
282
283 struct d30v_reloc_map
284 {
285 unsigned char bfd_reloc_val;
286 unsigned char elf_reloc_val;
287 };
288
289
290 static const struct d30v_reloc_map d30v_reloc_map[] =
291 {
292 { BFD_RELOC_NONE, R_D30V_NONE, },
293 { BFD_RELOC_D30V_6, R_D30V_6 },
294 { BFD_RELOC_D30V_15, R_D30V_15 },
295 { BFD_RELOC_D30V_15_PCREL, R_D30V_15_PCREL },
296 { BFD_RELOC_D30V_21, R_D30V_21 },
297 { BFD_RELOC_D30V_21_PCREL, R_D30V_21_PCREL },
298 { BFD_RELOC_D30V_32, R_D30V_32 },
299 { BFD_RELOC_D30V_32_PCREL, R_D30V_32_PCREL },
300 { BFD_RELOC_32, R_D30V_32_NORMAL },
301 };
302
303 static reloc_howto_type *
304 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
305 bfd *abfd;
306 bfd_reloc_code_real_type code;
307 {
308 unsigned int i;
309
310 for (i = 0;
311 i < sizeof (d30v_reloc_map) / sizeof (struct d30v_reloc_map);
312 i++)
313 {
314 if (d30v_reloc_map[i].bfd_reloc_val == code)
315 return &elf_d30v_howto_table[d30v_reloc_map[i].elf_reloc_val];
316 }
317
318 return NULL;
319 }
320
321 /* Set the howto pointer for an D30V ELF reloc. */
322
323 static void
324 d30v_info_to_howto_rel (abfd, cache_ptr, dst)
325 bfd *abfd;
326 arelent *cache_ptr;
327 Elf32_Internal_Rel *dst;
328 {
329 unsigned int r_type;
330
331 r_type = ELF32_R_TYPE (dst->r_info);
332 BFD_ASSERT (r_type < (unsigned int) R_D30V_max);
333 cache_ptr->howto = &elf_d30v_howto_table[r_type];
334 }
335
336 #define ELF_ARCH bfd_arch_d30v
337 #define ELF_MACHINE_CODE EM_CYGNUS_D30V
338 #define ELF_MAXPAGESIZE 0x1000
339
340 #define TARGET_BIG_SYM bfd_elf32_d30v_vec
341 #define TARGET_BIG_NAME "elf32-d30v"
342
343 #define elf_info_to_howto 0
344 #define elf_info_to_howto_rel d30v_info_to_howto_rel
345 #define elf_backend_object_p 0
346 #define elf_backend_final_write_processing 0
347
348 #include "elf32-target.h"
This page took 0.070451 seconds and 5 git commands to generate.