* elf32-v850.c (elf_v850_howto_table): Fix ordering of
[deliverable/binutils-gdb.git] / bfd / elf32-v850.c
CommitLineData
01b49cb3
C
1/* V850-specific support for 32-bit ELF
2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
3
4This file is part of BFD, the Binary File Descriptor library.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20#include "bfd.h"
21#include "sysdep.h"
725b96f5 22#include "bfdlink.h"
01b49cb3
C
23#include "libbfd.h"
24#include "elf-bfd.h"
25
26static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
27 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
28static void v850_info_to_howto_rel
29 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
e73b6ae6
JL
30static bfd_reloc_status_type bfd_elf32_v850_reloc
31 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
32
01b49cb3
C
33
34
35/* Try to minimize the amount of space occupied by relocation tables
36 on the ROM (not that the ROM won't be swamped by other ELF overhead). */
37#define USE_REL
38
39enum reloc_type
40{
41 R_V850_NONE = 0,
42 R_V850_9_PCREL,
43 R_V850_22_PCREL,
44 R_V850_HI16_S,
45 R_V850_HI16,
46 R_V850_LO16,
237b5c4c
JL
47 R_V850_32,
48 R_V850_16,
49 R_V850_8,
b6d08fce
JL
50 R_V850_SDA_OFFSET,
51 R_V850_ZDA_OFFSET,
52 R_V850_TDA_OFFSET,
01b49cb3
C
53 R_V850_max
54};
55
56static reloc_howto_type elf_v850_howto_table[] =
57{
58 /* This reloc does nothing. */
59 HOWTO (R_V850_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_V850_NONE", /* name */
68 false, /* partial_inplace */
69 0, /* src_mask */
70 0, /* dst_mask */
71 false), /* pcrel_offset */
72
73 /* A PC relative 9 bit branch. */
74 HOWTO (R_V850_9_PCREL, /* type */
75 2, /* rightshift */
76 2, /* size (0 = byte, 1 = short, 2 = long) */
77 26, /* bitsize */
78 true, /* pc_relative */
79 0, /* bitpos */
80 complain_overflow_bitfield, /* complain_on_overflow */
e73b6ae6 81 bfd_elf32_v850_reloc, /* special_function */
01b49cb3
C
82 "R_V850_9_PCREL", /* name */
83 false, /* partial_inplace */
84 0x00ffffff, /* src_mask */
85 0x00ffffff, /* dst_mask */
86 true), /* pcrel_offset */
87
88 /* A PC relative 22 bit branch. */
89 HOWTO (R_V850_22_PCREL, /* type */
90 2, /* rightshift */
91 2, /* size (0 = byte, 1 = short, 2 = long) */
92 22, /* bitsize */
93 true, /* pc_relative */
94 7, /* bitpos */
95 complain_overflow_signed, /* complain_on_overflow */
e73b6ae6 96 bfd_elf32_v850_reloc, /* special_function */
01b49cb3
C
97 "R_V850_22_PCREL", /* name */
98 false, /* partial_inplace */
99 0x07ffff80, /* src_mask */
100 0x07ffff80, /* dst_mask */
101 true), /* pcrel_offset */
102
103 /* High 16 bits of symbol value. */
104 HOWTO (R_V850_HI16_S, /* type */
105 0, /* rightshift */
106 1, /* size (0 = byte, 1 = short, 2 = long) */
107 16, /* bitsize */
108 false, /* pc_relative */
e73b6ae6 109 0, /* bitpos */
01b49cb3 110 complain_overflow_dont,/* complain_on_overflow */
e73b6ae6 111 bfd_elf32_v850_reloc, /* special_function */
01b49cb3
C
112 "R_V850_HI16_S", /* name */
113 true, /* partial_inplace */
114 0xffff, /* src_mask */
115 0xffff, /* dst_mask */
116 false), /* pcrel_offset */
117
118 /* High 16 bits of symbol value. */
119 HOWTO (R_V850_HI16, /* type */
120 0, /* rightshift */
121 1, /* size (0 = byte, 1 = short, 2 = long) */
122 16, /* bitsize */
123 false, /* pc_relative */
e73b6ae6 124 0, /* bitpos */
01b49cb3 125 complain_overflow_dont,/* complain_on_overflow */
e73b6ae6 126 bfd_elf32_v850_reloc, /* special_function */
01b49cb3
C
127 "R_V850_HI16", /* name */
128 true, /* partial_inplace */
129 0xffff, /* src_mask */
130 0xffff, /* dst_mask */
131 false), /* pcrel_offset */
132
133 /* Low 16 bits of symbol value. */
134 HOWTO (R_V850_LO16, /* type */
135 0, /* rightshift */
136 1, /* size (0 = byte, 1 = short, 2 = long) */
137 16, /* bitsize */
138 false, /* pc_relative */
e73b6ae6 139 0, /* bitpos */
01b49cb3
C
140 complain_overflow_dont,/* complain_on_overflow */
141 bfd_elf_generic_reloc, /* special_function */
142 "R_V850_LO16", /* name */
143 true, /* partial_inplace */
144 0xffff, /* src_mask */
145 0xffff, /* dst_mask */
146 false), /* pcrel_offset */
237b5c4c
JL
147
148 /* Simple 32bit reloc. */
149 HOWTO (R_V850_32, /* type */
150 0, /* rightshift */
151 2, /* size (0 = byte, 1 = short, 2 = long) */
152 32, /* bitsize */
153 false, /* pc_relative */
154 0, /* bitpos */
155 complain_overflow_dont,/* complain_on_overflow */
156 bfd_elf_generic_reloc, /* special_function */
157 "R_V850_32", /* name */
e73b6ae6
JL
158 true, /* partial_inplace */
159 0xffffffff, /* src_mask */
237b5c4c
JL
160 0xffffffff, /* dst_mask */
161 false), /* pcrel_offset */
162
163 /* Simple 16bit reloc. */
164 HOWTO (R_V850_16, /* type */
165 0, /* rightshift */
166 1, /* size (0 = byte, 1 = short, 2 = long) */
167 16, /* bitsize */
168 false, /* pc_relative */
169 0, /* bitpos */
170 complain_overflow_dont,/* complain_on_overflow */
171 bfd_elf_generic_reloc, /* special_function */
172 "R_V850_16", /* name */
e73b6ae6
JL
173 true, /* partial_inplace */
174 0xffff, /* src_mask */
237b5c4c
JL
175 0xffff, /* dst_mask */
176 false), /* pcrel_offset */
177
178 /* Simple 8bit reloc. */
179 HOWTO (R_V850_8, /* type */
180 0, /* rightshift */
181 0, /* size (0 = byte, 1 = short, 2 = long) */
182 8, /* bitsize */
183 false, /* pc_relative */
184 0, /* bitpos */
185 complain_overflow_dont,/* complain_on_overflow */
186 bfd_elf_generic_reloc, /* special_function */
187 "R_V850_8", /* name */
e73b6ae6
JL
188 true, /* partial_inplace */
189 0xff, /* src_mask */
237b5c4c
JL
190 0xff, /* dst_mask */
191 false), /* pcrel_offset */
b6d08fce
JL
192
193 /* Offset from the short data area pointer. */
194 HOWTO (R_V850_SDA_OFFSET, /* type */
195 0, /* rightshift */
c322f1b5 196 0, /* size (0 = byte, 1 = short, 2 = long) */
b6d08fce
JL
197 16, /* bitsize */
198 false, /* pc_relative */
199 0, /* bitpos */
200 complain_overflow_dont,/* complain_on_overflow */
201 bfd_elf_generic_reloc, /* special_function */
202 "R_V850_SDA_OFFSET", /* name */
203 true, /* partial_inplace */
204 0xffff, /* src_mask */
205 0xffff, /* dst_mask */
206 false), /* pcrel_offset */
207
c322f1b5
JL
208 /* Offset from the zero data area pointer. */
209 HOWTO (R_V850_ZDA_OFFSET, /* type */
b6d08fce
JL
210 0, /* rightshift */
211 1, /* size (0 = byte, 1 = short, 2 = long) */
212 16, /* bitsize */
213 false, /* pc_relative */
214 0, /* bitpos */
215 complain_overflow_dont,/* complain_on_overflow */
216 bfd_elf_generic_reloc, /* special_function */
c322f1b5 217 "R_V850_ZDA_OFFSET", /* name */
b6d08fce
JL
218 true, /* partial_inplace */
219 0xffff, /* src_mask */
220 0xffff, /* dst_mask */
221 false), /* pcrel_offset */
222
c322f1b5
JL
223 /* Offset from the tiny data area pointer. */
224 HOWTO (R_V850_TDA_OFFSET, /* type */
b6d08fce 225 0, /* rightshift */
c322f1b5
JL
226 2, /* size (0 = byte, 1 = short, 2 = long) */
227 8, /* bitsize */
b6d08fce
JL
228 false, /* pc_relative */
229 0, /* bitpos */
230 complain_overflow_dont,/* complain_on_overflow */
231 bfd_elf_generic_reloc, /* special_function */
c322f1b5 232 "R_V850_TDA_OFFSET", /* name */
b6d08fce 233 true, /* partial_inplace */
c322f1b5
JL
234 0xff, /* src_mask */
235 0xff, /* dst_mask */
b6d08fce
JL
236 false), /* pcrel_offset */
237
01b49cb3
C
238};
239
240/* Map BFD reloc types to V850 ELF reloc types. */
241
242struct v850_reloc_map
243{
244 unsigned char bfd_reloc_val;
245 unsigned char elf_reloc_val;
246};
247
248static const struct v850_reloc_map v850_reloc_map[] =
249{
250 { BFD_RELOC_NONE, R_V850_NONE, },
251 { BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL, },
252 { BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL, },
253 { BFD_RELOC_HI16_S, R_V850_HI16_S, },
254 { BFD_RELOC_HI16, R_V850_HI16, },
255 { BFD_RELOC_LO16, R_V850_LO16, },
237b5c4c
JL
256 { BFD_RELOC_32, R_V850_32, },
257 { BFD_RELOC_16, R_V850_16, },
258 { BFD_RELOC_8, R_V850_8, },
b6d08fce
JL
259 { BFD_RELOC_V850_TDA_OFFSET, R_V850_TDA_OFFSET, },
260 { BFD_RELOC_V850_SDA_OFFSET, R_V850_SDA_OFFSET, },
261 { BFD_RELOC_V850_ZDA_OFFSET, R_V850_ZDA_OFFSET, },
01b49cb3
C
262};
263
264static reloc_howto_type *
265bfd_elf32_bfd_reloc_type_lookup (abfd, code)
266 bfd *abfd;
267 bfd_reloc_code_real_type code;
268{
269 unsigned int i;
270
271 for (i = 0;
272 i < sizeof (v850_reloc_map) / sizeof (struct v850_reloc_map);
273 i++)
274 {
275 if (v850_reloc_map[i].bfd_reloc_val == code)
276 return &elf_v850_howto_table[v850_reloc_map[i].elf_reloc_val];
277 }
278
279 return NULL;
280}
281
282/* Set the howto pointer for an V850 ELF reloc. */
283
284static void
285v850_info_to_howto_rel (abfd, cache_ptr, dst)
286 bfd *abfd;
287 arelent *cache_ptr;
288 Elf32_Internal_Rel *dst;
289{
290 unsigned int r_type;
291
292 r_type = ELF32_R_TYPE (dst->r_info);
293 BFD_ASSERT (r_type < (unsigned int) R_V850_max);
294 cache_ptr->howto = &elf_v850_howto_table[r_type];
295}
296
e73b6ae6
JL
297static bfd_reloc_status_type
298bfd_elf32_v850_reloc (abfd, reloc, symbol, data, isection, obfd, err)
299 bfd *abfd;
300 arelent *reloc;
301 asymbol *symbol;
302 PTR data;
303 asection *isection;
304 bfd *obfd;
305 char **err;
306{
307 if (obfd != (bfd *) NULL
308 && (symbol->flags & BSF_SECTION_SYM) == 0
309 && (! reloc->howto->partial_inplace
310 || reloc->addend == 0))
311 {
312 reloc->address += isection->output_offset;
313 return bfd_reloc_ok;
314 }
315 else if (obfd != NULL)
316 {
317 return bfd_reloc_continue;
318 }
319
05f1baaa
JL
320 /* Catch relocs involving undefined symbols. */
321 if (bfd_is_und_section (symbol->section)
322 && (symbol->flags & BSF_WEAK) == 0
323 && obfd == NULL)
324 return bfd_reloc_undefined;
325
e73b6ae6
JL
326 /* We handle final linking of some relocs ourselves. */
327 {
328 long relocation, insn;
329
330 /* Is the address of the relocation really within the section? */
331 if (reloc->address > isection->_cooked_size)
332 return bfd_reloc_outofrange;
333
334 /* Work out which section the relocation is targetted at and the
335 initial relocation command value. */
336
337 /* Get symbol value. (Common symbols are special.) */
338 if (bfd_is_com_section (symbol->section))
339 relocation = 0;
340 else
341 relocation = symbol->value;
342
343 /* Convert input-section-relative symbol value to absolute + addend. */
344 relocation += symbol->section->output_section->vma;
345 relocation += symbol->section->output_offset;
346 relocation += reloc->addend;
347
348 if (reloc->howto->pc_relative == true)
349 {
350 /* Here the variable relocation holds the final address of the
351 symbol we are relocating against, plus any addend. */
352 relocation -= isection->output_section->vma + isection->output_offset;
353
354 /* Deal with pcrel_offset */
355 relocation -= reloc->address;
356 }
357
358 /* I've got no clue... */
359 reloc->addend = 0;
360
361 if (reloc->howto->type == R_V850_22_PCREL)
362 {
363 if (relocation > 0x1ffff || relocation < -0x200000)
364 return bfd_reloc_overflow;
365
366 if ((relocation % 2) != 0)
367 return bfd_reloc_dangerous;
368
369 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
e1d98a0a 370 insn &= ~0xfffe003f;
e73b6ae6
JL
371 insn |= (((relocation & 0xfffe) << 16)
372 | ((relocation & 0x3f0000) >> 16));
373 bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
374 return bfd_reloc_ok;
375 }
376 else if (reloc->howto->type == R_V850_9_PCREL)
377 {
378 if (relocation > 0xff || relocation < -0x100)
379 return bfd_reloc_overflow;
380
381 if ((relocation % 2) != 0)
382 return bfd_reloc_dangerous;
383
384 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
e1d98a0a 385 insn &= 0xf870;
e73b6ae6
JL
386 insn |= ((relocation & 0x1f0) << 7) | ((relocation & 0x0e) << 3);
387 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
388 return bfd_reloc_ok;
389 }
390 else if (reloc->howto->type == R_V850_HI16_S)
391 {
1336da39 392 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
e73b6ae6
JL
393 relocation = (relocation >> 16) + ((relocation & 0x8000) != 0);
394 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
395 return bfd_reloc_ok;
396 }
397 else if (reloc->howto->type == R_V850_HI16)
398 {
1336da39 399 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
e73b6ae6
JL
400 relocation = (relocation >> 16);
401 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
402 return bfd_reloc_ok;
403 }
725b96f5
JL
404 else
405 return bfd_reloc_notsupported;
e73b6ae6
JL
406 }
407
408 return bfd_reloc_continue;
409}
410
1336da39
SG
411static boolean bfd_elf32_v850_is_local_label PARAMS ((bfd *, asymbol *));
412
413/*ARGSUSED*/
414static boolean
415bfd_elf32_v850_is_local_label (abfd, symbol)
416 bfd *abfd;
417 asymbol *symbol;
418{
419 return ((symbol->name[0] == '.' && (symbol->name[1] == 'L' || symbol->name[1] == '.'))
420 || (symbol->name[0] == '_' && symbol->name[1] == '.' && symbol->name[2] == 'L'
421 && symbol->name[3] == '_'));
422}
423
725b96f5
JL
424/* Perform a relocation as part of a final link. */
425static bfd_reloc_status_type
426elf32_v850_bfd_final_link_relocate (howto, input_bfd, output_bfd,
427 input_section, contents, offset, value,
428 addend, info, sym_sec, is_local)
429 reloc_howto_type *howto;
430 bfd *input_bfd;
431 bfd *output_bfd;
432 asection *input_section;
433 bfd_byte *contents;
434 bfd_vma offset;
435 bfd_vma value;
436 bfd_vma addend;
437 struct bfd_link_info *info;
438 asection *sym_sec;
439 int is_local;
440{
441 unsigned long insn;
442 unsigned long r_type = howto->type;
443 unsigned long r_format = howto->bitsize;
444 bfd_byte *hit_data = contents + offset;
445 boolean r_pcrel = howto->pc_relative;
446
447 switch (r_type)
448 {
449 case R_V850_9_PCREL:
450 value -= (input_section->output_section->vma
451 + input_section->output_offset);
452 value -= offset;
453
454 if ((long)value > 0xff || (long)value < -0x100)
455 return bfd_reloc_overflow;
456
457 if ((value % 2) != 0)
458 return bfd_reloc_dangerous;
459
460 insn = bfd_get_16 (input_bfd, hit_data);
c322f1b5 461 insn &= 0x078f;
725b96f5
JL
462 insn |= ((value & 0x1f0) << 7) | ((value & 0x0e) << 3);
463 bfd_put_16 (input_bfd, insn, hit_data);
464 return bfd_reloc_ok;
465
466 case R_V850_22_PCREL:
467 value -= (input_section->output_section->vma
468 + input_section->output_offset);
469 value -= offset;
470
471 if ((long)value > 0x1ffff || (long)value < -0x200000)
472 return bfd_reloc_overflow;
473
474 if ((value % 2) != 0)
475 return bfd_reloc_dangerous;
476
477 insn = bfd_get_32 (input_bfd, hit_data);
c322f1b5 478 insn &= 0x1ffc0;
725b96f5
JL
479 insn |= (((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16));
480 bfd_put_32 (input_bfd, insn, hit_data);
481 return bfd_reloc_ok;
482
483 case R_V850_HI16_S:
484 value += bfd_get_16 (input_bfd, hit_data);
485 value = (value >> 16) + ((value & 0x8000) != 0);
486
487 if ((long)value > 0x7fff || (long)value < -0x8000)
488 return bfd_reloc_overflow;
489
490 bfd_put_16 (input_bfd, value, hit_data);
491 return bfd_reloc_ok;
492
493 case R_V850_HI16:
494 value += bfd_get_16 (input_bfd, hit_data);
495 value >>= 16;
496
497 if ((long)value > 0x7fff || (long)value < -0x8000)
498 return bfd_reloc_overflow;
499
500 bfd_put_16 (input_bfd, value, hit_data);
501 return bfd_reloc_ok;
502
503 case R_V850_LO16:
504 value += bfd_get_16 (input_bfd, hit_data);
505 value &= 0xffff;
506
507 bfd_put_16 (input_bfd, value, hit_data);
508 return bfd_reloc_ok;
509
510 case R_V850_16:
511 case R_V850_ZDA_OFFSET:
512 value += bfd_get_16 (input_bfd, hit_data);
513
514 if ((long)value > 0x7fff || (long)value < -0x8000)
515 return bfd_reloc_overflow;
516
517 bfd_put_16 (input_bfd, value, hit_data);
518 return bfd_reloc_ok;
519
520 case R_V850_32:
521 value += bfd_get_32 (input_bfd, hit_data);
522 bfd_put_32 (input_bfd, value, hit_data);
523 return bfd_reloc_ok;
524
525 case R_V850_8:
526 value += bfd_get_8 (input_bfd, hit_data);
527
528 if ((long)value > 0x7f || (long)value < -0x80)
529 return bfd_reloc_overflow;
530
531 bfd_put_8 (input_bfd, value, hit_data);
532 return bfd_reloc_ok;
533
534 case R_V850_SDA_OFFSET:
535 {
536 unsigned long gp;
537 struct bfd_link_hash_entry *h;
538
539 value += bfd_get_16 (input_bfd, hit_data);
540
541 /* Get the value of __gp. */
542 h = bfd_link_hash_lookup (info->hash, "__gp", false,
543 false, true);
544 if (h == (struct bfd_link_hash_entry *) NULL
545 || h->type != bfd_link_hash_defined)
546 return bfd_reloc_undefined;
547
548 gp = (h->u.def.value
549 + h->u.def.section->output_section->vma
550 + h->u.def.section->output_offset);
551 value -= gp;
552
553 if ((long)value > 0x7fff || (long)value < -0x8000)
554 return bfd_reloc_overflow;
555
556 bfd_put_16 (input_bfd, value, hit_data);
557 return bfd_reloc_ok;
558 }
559
560 case R_V850_TDA_OFFSET:
561 {
562 unsigned long ep;
563 struct bfd_link_hash_entry *h;
564
c322f1b5 565 insn = bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
566
567 /* Get the value of __ep. */
568 h = bfd_link_hash_lookup (info->hash, "__ep", false,
569 false, true);
570 if (h == (struct bfd_link_hash_entry *) NULL
571 || h->type != bfd_link_hash_defined)
572 return bfd_reloc_undefined;
573
574 ep = (h->u.def.value
575 + h->u.def.section->output_section->vma
576 + h->u.def.section->output_offset);
577 value -= ep;
578
579
c322f1b5
JL
580 /* Overflow computation and operand insertion is complicated
581 by valid offsets and insertions changing depending on the
582 instruction being used! */
583 if ((insn & 0x0780) == 0x0500)
584 {
585 value += ((insn & 0x7f) << 2);
586
587 /* Handle sld.w and sst.w -- 8 bit unsigned offset */
588 if ((long) value > 0xff || (long) value < 0)
589 return bfd_reloc_overflow;
590
591 if ((value % 4) != 0)
592 return bfd_reloc_dangerous;
593
594 insn &= 0xff81;
595 insn |= (value >> 1);
596 bfd_put_16 (input_bfd, insn, hit_data);
597 return bfd_reloc_ok;
598 }
599
600 if ((insn & 0x0780) == 0x0400 || (insn & 0x0780) == 0x0480)
601 {
602 value += ((insn & 0x7f) << 1);
603
604 /* Handle sld.h and sst.h -- 8 bit unsigned offset */
605 if ((long) value > 0xff || (long) value < 0)
606 return bfd_reloc_overflow;
607
608 if ((value % 2) != 0)
609 return bfd_reloc_dangerous;
610
611 insn &= 0xff80;
612 insn |= (value >> 1);
613 bfd_put_16 (input_bfd, insn, hit_data);
614 return bfd_reloc_ok;
615 }
616
617 if ((insn & 0x0780) == 0x0300 || (insn & 0x0780) == 0x0380)
618 {
619 value += (insn & 0x7f);
620
621 /* Handle sld.b and sst.b -- 7 bit unsigned offset */
622 if ((long) value > 0x7f || (long) value < 0)
623 return bfd_reloc_overflow;
624 insn &= 0xff80;
625 insn |= value;
626 bfd_put_16 (input_bfd, insn, hit_data);
627 return bfd_reloc_ok;
628 }
629
630 /* Guess (XXX) that it's a movea instruction or something
631 similar. */
632 value += insn;
633 if ((long)value > 0x7fff || (long)value < -0x8000)
634 return bfd_reloc_overflow;
635
636 bfd_put_16 (input_bfd, value, hit_data);
637 return bfd_reloc_ok;
725b96f5
JL
638 }
639
640 case R_V850_NONE:
641 default:
642 break;
643 }
644
645}
646
647/* Relocate an V850 ELF section. */
648
649static boolean
650v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
651 contents, relocs, local_syms, local_sections)
652 bfd *output_bfd;
653 struct bfd_link_info *info;
654 bfd *input_bfd;
655 asection *input_section;
656 bfd_byte *contents;
657 Elf_Internal_Rela *relocs;
658 Elf_Internal_Sym *local_syms;
659 asection **local_sections;
660{
661 Elf_Internal_Shdr *symtab_hdr;
662 struct elf_link_hash_entry **sym_hashes;
663 Elf_Internal_Rela *rel, *relend;
664
665 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
666 sym_hashes = elf_sym_hashes (input_bfd);
667
668 rel = relocs;
669 relend = relocs + input_section->reloc_count;
670 for (; rel < relend; rel++)
671 {
672 int r_type;
673 reloc_howto_type *howto;
674 unsigned long r_symndx;
675 Elf_Internal_Sym *sym;
676 asection *sec;
677 struct elf_link_hash_entry *h;
678 bfd_vma relocation;
679 bfd_reloc_status_type r;
680
681 if (info->relocateable)
682 {
683 /* This is a relocateable link. We don't have to change
684 anything, unless the reloc is against a section symbol,
685 in which case we have to adjust according to where the
686 section symbol winds up in the output section. */
687 if (r_symndx < symtab_hdr->sh_info)
688 {
689 sym = local_syms + r_symndx;
690 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
691 {
692 sec = local_sections[r_symndx];
693 rel->r_addend += sec->output_offset + sym->st_value;
694 }
695 }
696
697 continue;
698 }
699
700 r_type = ELF32_R_TYPE (rel->r_info);
701
702 howto = elf_v850_howto_table + r_type;
703
704 r_symndx = ELF32_R_SYM (rel->r_info);
705
706 /* This is a final link. */
707 h = NULL;
708 sym = NULL;
709 sec = NULL;
710 if (r_symndx < symtab_hdr->sh_info)
711 {
712 sym = local_syms + r_symndx;
713 sec = local_sections[r_symndx];
714 relocation = (sec->output_section->vma
715 + sec->output_offset
716 + sym->st_value);
717 }
718 else
719 {
720 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
721 while (h->root.type == bfd_link_hash_indirect
722 || h->root.type == bfd_link_hash_warning)
723 h = (struct elf_link_hash_entry *) h->root.u.i.link;
724 if (h->root.type == bfd_link_hash_defined
725 || h->root.type == bfd_link_hash_defweak)
726 {
727 sec = h->root.u.def.section;
728 relocation = (h->root.u.def.value
729 + sec->output_section->vma
730 + sec->output_offset);
731 }
732 else if (h->root.type == bfd_link_hash_undefweak)
733 relocation = 0;
734 else
735 {
736 if (! ((*info->callbacks->undefined_symbol)
737 (info, h->root.root.string, input_bfd,
738 input_section, rel->r_offset)))
739 return false;
740 relocation = 0;
741 }
742 }
743
744 /* FIXME: We should use the addend, but the COFF relocations
745 don't. */
746 r = elf32_v850_bfd_final_link_relocate (howto, input_bfd, output_bfd,
747 input_section,
748 contents, rel->r_offset,
749 relocation, rel->r_addend,
750 info, sec, h == NULL);
751
752 if (r != bfd_reloc_ok)
753 {
754 switch (r)
755 {
756 default:
757 case bfd_reloc_outofrange:
758 abort ();
759 case bfd_reloc_overflow:
760 {
761 const char *name;
762
763 if (h != NULL)
764 name = h->root.root.string;
765 else
766 {
767 name = (bfd_elf_string_from_elf_section
768 (input_bfd, symtab_hdr->sh_link, sym->st_name));
769 if (name == NULL)
770 return false;
771 if (*name == '\0')
772 name = bfd_section_name (input_bfd, sec);
773 }
774 if (! ((*info->callbacks->reloc_overflow)
775 (info, name, howto->name, (bfd_vma) 0,
776 input_bfd, input_section, rel->r_offset)))
777 return false;
778 }
779 break;
780 }
781 }
782 }
783
784 return true;
785}
1336da39
SG
786#define bfd_elf32_bfd_is_local_label bfd_elf32_v850_is_local_label
787
e73b6ae6
JL
788#define TARGET_LITTLE_SYM bfd_elf32_v850_vec
789#define TARGET_LITTLE_NAME "elf32-v850"
01b49cb3
C
790#define ELF_ARCH bfd_arch_v850
791#define ELF_MACHINE_CODE EM_CYGNUS_V850
792#define ELF_MAXPAGESIZE 0x1000
793
794#define elf_info_to_howto 0
795#define elf_info_to_howto_rel v850_info_to_howto_rel
725b96f5
JL
796#define elf_backend_relocate_section v850_elf_relocate_section
797
01b49cb3 798
1336da39
SG
799#define elf_symbol_leading_char '_'
800
01b49cb3 801#include "elf32-target.h"
This page took 0.061556 seconds and 4 git commands to generate.