* elf32-v850.c: Define elf_symbol_leading_char to be '_'.
[deliverable/binutils-gdb.git] / bfd / elf32-v850.c
1 /* V850-specific support for 32-bit ELF
2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
3
4 This file is part of BFD, the Binary File Descriptor library.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20 #include "bfd.h"
21 #include "sysdep.h"
22 #include "libbfd.h"
23 #include "elf-bfd.h"
24
25 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
26 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
27 static void v850_info_to_howto_rel
28 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
29 static bfd_reloc_status_type bfd_elf32_v850_reloc
30 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
31
32
33
34 /* Try to minimize the amount of space occupied by relocation tables
35 on the ROM (not that the ROM won't be swamped by other ELF overhead). */
36 #define USE_REL
37
38 enum reloc_type
39 {
40 R_V850_NONE = 0,
41 R_V850_9_PCREL,
42 R_V850_22_PCREL,
43 R_V850_HI16_S,
44 R_V850_HI16,
45 R_V850_LO16,
46 R_V850_32,
47 R_V850_16,
48 R_V850_8,
49 R_V850_max
50 };
51
52 static reloc_howto_type elf_v850_howto_table[] =
53 {
54 /* This reloc does nothing. */
55 HOWTO (R_V850_NONE, /* type */
56 0, /* rightshift */
57 2, /* size (0 = byte, 1 = short, 2 = long) */
58 32, /* bitsize */
59 false, /* pc_relative */
60 0, /* bitpos */
61 complain_overflow_bitfield, /* complain_on_overflow */
62 bfd_elf_generic_reloc, /* special_function */
63 "R_V850_NONE", /* name */
64 false, /* partial_inplace */
65 0, /* src_mask */
66 0, /* dst_mask */
67 false), /* pcrel_offset */
68
69 /* A PC relative 9 bit branch. */
70 HOWTO (R_V850_9_PCREL, /* type */
71 2, /* rightshift */
72 2, /* size (0 = byte, 1 = short, 2 = long) */
73 26, /* bitsize */
74 true, /* pc_relative */
75 0, /* bitpos */
76 complain_overflow_bitfield, /* complain_on_overflow */
77 bfd_elf32_v850_reloc, /* special_function */
78 "R_V850_9_PCREL", /* name */
79 false, /* partial_inplace */
80 0x00ffffff, /* src_mask */
81 0x00ffffff, /* dst_mask */
82 true), /* pcrel_offset */
83
84 /* A PC relative 22 bit branch. */
85 HOWTO (R_V850_22_PCREL, /* type */
86 2, /* rightshift */
87 2, /* size (0 = byte, 1 = short, 2 = long) */
88 22, /* bitsize */
89 true, /* pc_relative */
90 7, /* bitpos */
91 complain_overflow_signed, /* complain_on_overflow */
92 bfd_elf32_v850_reloc, /* special_function */
93 "R_V850_22_PCREL", /* name */
94 false, /* partial_inplace */
95 0x07ffff80, /* src_mask */
96 0x07ffff80, /* dst_mask */
97 true), /* pcrel_offset */
98
99 /* High 16 bits of symbol value. */
100 HOWTO (R_V850_HI16_S, /* type */
101 0, /* rightshift */
102 1, /* size (0 = byte, 1 = short, 2 = long) */
103 16, /* bitsize */
104 false, /* pc_relative */
105 0, /* bitpos */
106 complain_overflow_dont,/* complain_on_overflow */
107 bfd_elf32_v850_reloc, /* special_function */
108 "R_V850_HI16_S", /* name */
109 true, /* partial_inplace */
110 0xffff, /* src_mask */
111 0xffff, /* dst_mask */
112 false), /* pcrel_offset */
113
114 /* High 16 bits of symbol value. */
115 HOWTO (R_V850_HI16, /* type */
116 0, /* rightshift */
117 1, /* size (0 = byte, 1 = short, 2 = long) */
118 16, /* bitsize */
119 false, /* pc_relative */
120 0, /* bitpos */
121 complain_overflow_dont,/* complain_on_overflow */
122 bfd_elf32_v850_reloc, /* special_function */
123 "R_V850_HI16", /* name */
124 true, /* partial_inplace */
125 0xffff, /* src_mask */
126 0xffff, /* dst_mask */
127 false), /* pcrel_offset */
128
129 /* Low 16 bits of symbol value. */
130 HOWTO (R_V850_LO16, /* type */
131 0, /* rightshift */
132 1, /* size (0 = byte, 1 = short, 2 = long) */
133 16, /* bitsize */
134 false, /* pc_relative */
135 0, /* bitpos */
136 complain_overflow_dont,/* complain_on_overflow */
137 bfd_elf_generic_reloc, /* special_function */
138 "R_V850_LO16", /* name */
139 true, /* partial_inplace */
140 0xffff, /* src_mask */
141 0xffff, /* dst_mask */
142 false), /* pcrel_offset */
143
144 /* Simple 32bit reloc. */
145 HOWTO (R_V850_32, /* type */
146 0, /* rightshift */
147 2, /* size (0 = byte, 1 = short, 2 = long) */
148 32, /* bitsize */
149 false, /* pc_relative */
150 0, /* bitpos */
151 complain_overflow_dont,/* complain_on_overflow */
152 bfd_elf_generic_reloc, /* special_function */
153 "R_V850_32", /* name */
154 true, /* partial_inplace */
155 0xffffffff, /* src_mask */
156 0xffffffff, /* dst_mask */
157 false), /* pcrel_offset */
158
159 /* Simple 16bit reloc. */
160 HOWTO (R_V850_16, /* type */
161 0, /* rightshift */
162 1, /* size (0 = byte, 1 = short, 2 = long) */
163 16, /* bitsize */
164 false, /* pc_relative */
165 0, /* bitpos */
166 complain_overflow_dont,/* complain_on_overflow */
167 bfd_elf_generic_reloc, /* special_function */
168 "R_V850_16", /* name */
169 true, /* partial_inplace */
170 0xffff, /* src_mask */
171 0xffff, /* dst_mask */
172 false), /* pcrel_offset */
173
174 /* Simple 8bit reloc. */
175 HOWTO (R_V850_8, /* type */
176 0, /* rightshift */
177 0, /* size (0 = byte, 1 = short, 2 = long) */
178 8, /* bitsize */
179 false, /* pc_relative */
180 0, /* bitpos */
181 complain_overflow_dont,/* complain_on_overflow */
182 bfd_elf_generic_reloc, /* special_function */
183 "R_V850_8", /* name */
184 true, /* partial_inplace */
185 0xff, /* src_mask */
186 0xff, /* dst_mask */
187 false), /* pcrel_offset */
188 };
189
190 /* Map BFD reloc types to V850 ELF reloc types. */
191
192 struct v850_reloc_map
193 {
194 unsigned char bfd_reloc_val;
195 unsigned char elf_reloc_val;
196 };
197
198 static const struct v850_reloc_map v850_reloc_map[] =
199 {
200 { BFD_RELOC_NONE, R_V850_NONE, },
201 { BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL, },
202 { BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL, },
203 { BFD_RELOC_HI16_S, R_V850_HI16_S, },
204 { BFD_RELOC_HI16, R_V850_HI16, },
205 { BFD_RELOC_LO16, R_V850_LO16, },
206 { BFD_RELOC_32, R_V850_32, },
207 { BFD_RELOC_16, R_V850_16, },
208 { BFD_RELOC_8, R_V850_8, },
209 };
210
211 static reloc_howto_type *
212 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
213 bfd *abfd;
214 bfd_reloc_code_real_type code;
215 {
216 unsigned int i;
217
218 for (i = 0;
219 i < sizeof (v850_reloc_map) / sizeof (struct v850_reloc_map);
220 i++)
221 {
222 if (v850_reloc_map[i].bfd_reloc_val == code)
223 return &elf_v850_howto_table[v850_reloc_map[i].elf_reloc_val];
224 }
225
226 return NULL;
227 }
228
229 /* Set the howto pointer for an V850 ELF reloc. */
230
231 static void
232 v850_info_to_howto_rel (abfd, cache_ptr, dst)
233 bfd *abfd;
234 arelent *cache_ptr;
235 Elf32_Internal_Rel *dst;
236 {
237 unsigned int r_type;
238
239 r_type = ELF32_R_TYPE (dst->r_info);
240 BFD_ASSERT (r_type < (unsigned int) R_V850_max);
241 cache_ptr->howto = &elf_v850_howto_table[r_type];
242 }
243
244 static bfd_reloc_status_type
245 bfd_elf32_v850_reloc (abfd, reloc, symbol, data, isection, obfd, err)
246 bfd *abfd;
247 arelent *reloc;
248 asymbol *symbol;
249 PTR data;
250 asection *isection;
251 bfd *obfd;
252 char **err;
253 {
254 if (obfd != (bfd *) NULL
255 && (symbol->flags & BSF_SECTION_SYM) == 0
256 && (! reloc->howto->partial_inplace
257 || reloc->addend == 0))
258 {
259 reloc->address += isection->output_offset;
260 return bfd_reloc_ok;
261 }
262 else if (obfd != NULL)
263 {
264 return bfd_reloc_continue;
265 }
266
267 /* We handle final linking of some relocs ourselves. */
268 {
269 long relocation, insn;
270
271 /* Is the address of the relocation really within the section? */
272 if (reloc->address > isection->_cooked_size)
273 return bfd_reloc_outofrange;
274
275 /* Work out which section the relocation is targetted at and the
276 initial relocation command value. */
277
278 /* Get symbol value. (Common symbols are special.) */
279 if (bfd_is_com_section (symbol->section))
280 relocation = 0;
281 else
282 relocation = symbol->value;
283
284 /* Convert input-section-relative symbol value to absolute + addend. */
285 relocation += symbol->section->output_section->vma;
286 relocation += symbol->section->output_offset;
287 relocation += reloc->addend;
288
289 if (reloc->howto->pc_relative == true)
290 {
291 /* Here the variable relocation holds the final address of the
292 symbol we are relocating against, plus any addend. */
293 relocation -= isection->output_section->vma + isection->output_offset;
294
295 /* Deal with pcrel_offset */
296 relocation -= reloc->address;
297 }
298
299 /* I've got no clue... */
300 reloc->addend = 0;
301
302 if (reloc->howto->type == R_V850_22_PCREL)
303 {
304 if (relocation > 0x1ffff || relocation < -0x200000)
305 return bfd_reloc_overflow;
306
307 if ((relocation % 2) != 0)
308 return bfd_reloc_dangerous;
309
310 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
311 insn |= (((relocation & 0xfffe) << 16)
312 | ((relocation & 0x3f0000) >> 16));
313 bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
314 return bfd_reloc_ok;
315 }
316 else if (reloc->howto->type == R_V850_9_PCREL)
317 {
318 if (relocation > 0xff || relocation < -0x100)
319 return bfd_reloc_overflow;
320
321 if ((relocation % 2) != 0)
322 return bfd_reloc_dangerous;
323
324 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
325 insn |= ((relocation & 0x1f0) << 7) | ((relocation & 0x0e) << 3);
326 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
327 return bfd_reloc_ok;
328 }
329 else if (reloc->howto->type == R_V850_HI16_S)
330 {
331 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
332 relocation = (relocation >> 16) + ((relocation & 0x8000) != 0);
333 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
334 return bfd_reloc_ok;
335 }
336 else if (reloc->howto->type == R_V850_HI16)
337 {
338 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
339 relocation = (relocation >> 16);
340 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
341 return bfd_reloc_ok;
342 }
343 }
344
345 return bfd_reloc_continue;
346 }
347
348 static boolean bfd_elf32_v850_is_local_label PARAMS ((bfd *, asymbol *));
349
350 /*ARGSUSED*/
351 static boolean
352 bfd_elf32_v850_is_local_label (abfd, symbol)
353 bfd *abfd;
354 asymbol *symbol;
355 {
356 return ((symbol->name[0] == '.' && (symbol->name[1] == 'L' || symbol->name[1] == '.'))
357 || (symbol->name[0] == '_' && symbol->name[1] == '.' && symbol->name[2] == 'L'
358 && symbol->name[3] == '_'));
359 }
360
361 #define bfd_elf32_bfd_is_local_label bfd_elf32_v850_is_local_label
362
363 #define TARGET_LITTLE_SYM bfd_elf32_v850_vec
364 #define TARGET_LITTLE_NAME "elf32-v850"
365 #define ELF_ARCH bfd_arch_v850
366 #define ELF_MACHINE_CODE EM_CYGNUS_V850
367 #define ELF_MAXPAGESIZE 0x1000
368
369 #define elf_info_to_howto 0
370 #define elf_info_to_howto_rel v850_info_to_howto_rel
371
372 #define elf_symbol_leading_char '_'
373
374 #include "elf32-target.h"
This page took 0.038852 seconds and 5 git commands to generate.