1 /* V850-specific support for 32-bit ELF
2 Copyright (C) 1996, 1997 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
22 /* XXX FIXME: This code is littered with 32bit int, 16bit short, 8bit char
23 dependencies. As is the gas & simulator code or the v850. */
33 static reloc_howto_type *v850_elf_reloc_type_lookup
34 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
35 static void v850_elf_info_to_howto_rel
36 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
37 static bfd_reloc_status_type v850_elf_reloc
38 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
39 static boolean v850_elf_is_local_label_name PARAMS ((bfd *, const char *));
40 static boolean v850_elf_relocate_section PARAMS((bfd *,
41 struct bfd_link_info *,
48 /* Try to minimize the amount of space occupied by relocation tables
49 on the ROM (not that the ROM won't be swamped by other ELF overhead). */
52 /* Note: It is REQUIRED that the 'type' value of each entry in this array
53 match the index of the entry in the array. */
54 static reloc_howto_type v850_elf_howto_table[] =
56 /* This reloc does nothing. */
57 HOWTO (R_V850_NONE, /* type */
59 2, /* size (0 = byte, 1 = short, 2 = long) */
61 false, /* pc_relative */
63 complain_overflow_bitfield, /* complain_on_overflow */
64 bfd_elf_generic_reloc, /* special_function */
65 "R_V850_NONE", /* name */
66 false, /* partial_inplace */
69 false), /* pcrel_offset */
71 /* A PC relative 9 bit branch. */
72 HOWTO (R_V850_9_PCREL, /* type */
74 2, /* size (0 = byte, 1 = short, 2 = long) */
76 true, /* pc_relative */
78 complain_overflow_bitfield, /* complain_on_overflow */
79 v850_elf_reloc, /* special_function */
80 "R_V850_9_PCREL", /* name */
81 false, /* partial_inplace */
82 0x00ffffff, /* src_mask */
83 0x00ffffff, /* dst_mask */
84 true), /* pcrel_offset */
86 /* A PC relative 22 bit branch. */
87 HOWTO (R_V850_22_PCREL, /* type */
89 2, /* size (0 = byte, 1 = short, 2 = long) */
91 true, /* pc_relative */
93 complain_overflow_signed, /* complain_on_overflow */
94 v850_elf_reloc, /* special_function */
95 "R_V850_22_PCREL", /* name */
96 false, /* partial_inplace */
97 0x07ffff80, /* src_mask */
98 0x07ffff80, /* dst_mask */
99 true), /* pcrel_offset */
101 /* High 16 bits of symbol value. */
102 HOWTO (R_V850_HI16_S, /* type */
104 1, /* size (0 = byte, 1 = short, 2 = long) */
106 false, /* pc_relative */
108 complain_overflow_dont, /* complain_on_overflow */
109 v850_elf_reloc, /* special_function */
110 "R_V850_HI16_S", /* name */
111 true, /* partial_inplace */
112 0xffff, /* src_mask */
113 0xffff, /* dst_mask */
114 false), /* pcrel_offset */
116 /* High 16 bits of symbol value. */
117 HOWTO (R_V850_HI16, /* type */
119 1, /* size (0 = byte, 1 = short, 2 = long) */
121 false, /* pc_relative */
123 complain_overflow_dont, /* complain_on_overflow */
124 v850_elf_reloc, /* special_function */
125 "R_V850_HI16", /* name */
126 true, /* partial_inplace */
127 0xffff, /* src_mask */
128 0xffff, /* dst_mask */
129 false), /* pcrel_offset */
131 /* Low 16 bits of symbol value. */
132 HOWTO (R_V850_LO16, /* type */
134 1, /* size (0 = byte, 1 = short, 2 = long) */
136 false, /* pc_relative */
138 complain_overflow_dont, /* complain_on_overflow */
139 v850_elf_reloc, /* special_function */
140 "R_V850_LO16", /* name */
141 true, /* partial_inplace */
142 0xffff, /* src_mask */
143 0xffff, /* dst_mask */
144 false), /* pcrel_offset */
146 /* Simple 32bit reloc. */
147 HOWTO (R_V850_32, /* type */
149 2, /* size (0 = byte, 1 = short, 2 = long) */
151 false, /* pc_relative */
153 complain_overflow_dont, /* complain_on_overflow */
154 bfd_elf_generic_reloc, /* special_function */
155 "R_V850_32", /* name */
156 true, /* partial_inplace */
157 0xffffffff, /* src_mask */
158 0xffffffff, /* dst_mask */
159 false), /* pcrel_offset */
161 /* Simple 16bit reloc. */
162 HOWTO (R_V850_16, /* type */
164 1, /* size (0 = byte, 1 = short, 2 = long) */
166 false, /* pc_relative */
168 complain_overflow_dont, /* complain_on_overflow */
169 bfd_elf_generic_reloc, /* special_function */
170 "R_V850_16", /* name */
171 true, /* partial_inplace */
172 0xffff, /* src_mask */
173 0xffff, /* dst_mask */
174 false), /* pcrel_offset */
176 /* Simple 8bit reloc. */
177 HOWTO (R_V850_8, /* type */
179 0, /* size (0 = byte, 1 = short, 2 = long) */
181 false, /* pc_relative */
183 complain_overflow_dont, /* complain_on_overflow */
184 bfd_elf_generic_reloc, /* special_function */
185 "R_V850_8", /* name */
186 true, /* partial_inplace */
189 false), /* pcrel_offset */
191 /* 16 bit offset from the short data area pointer. */
192 HOWTO (R_V850_SDA_16_16_OFFSET, /* type */
194 1, /* size (0 = byte, 1 = short, 2 = long) */
196 false, /* pc_relative */
198 complain_overflow_dont, /* complain_on_overflow */
199 v850_elf_reloc, /* special_function */
200 "R_V850_SDA_16_16_OFFSET", /* name */
201 false, /* partial_inplace */
202 0xffff, /* src_mask */
203 0xffff, /* dst_mask */
204 false), /* pcrel_offset */
206 /* 15 bit offset from the short data area pointer. */
207 HOWTO (R_V850_SDA_15_16_OFFSET, /* type */
209 1, /* size (0 = byte, 1 = short, 2 = long) */
211 false, /* pc_relative */
213 complain_overflow_dont, /* complain_on_overflow */
214 v850_elf_reloc, /* special_function */
215 "R_V850_SDA_15_16_OFFSET", /* name */
216 false, /* partial_inplace */
217 0xfffe, /* src_mask */
218 0xfffe, /* dst_mask */
219 false), /* pcrel_offset */
221 /* 16 bit offset from the zero data area pointer. */
222 HOWTO (R_V850_ZDA_16_16_OFFSET, /* type */
224 1, /* size (0 = byte, 1 = short, 2 = long) */
226 false, /* pc_relative */
228 complain_overflow_dont, /* complain_on_overflow */
229 v850_elf_reloc, /* special_function */
230 "R_V850_ZDA_16_16_OFFSET", /* name */
231 false, /* partial_inplace */
232 0xffff, /* src_mask */
233 0xffff, /* dst_mask */
234 false), /* pcrel_offset */
236 /* 15 bit offset from the zero data area pointer. */
237 HOWTO (R_V850_ZDA_15_16_OFFSET, /* type */
239 1, /* size (0 = byte, 1 = short, 2 = long) */
241 false, /* pc_relative */
243 complain_overflow_dont, /* complain_on_overflow */
244 v850_elf_reloc, /* special_function */
245 "R_V850_ZDA_15_16_OFFSET", /* name */
246 false, /* partial_inplace */
247 0xfffe, /* src_mask */
248 0xfffe, /* dst_mask */
249 false), /* pcrel_offset */
251 /* 6 bit offset from the tiny data area pointer. */
252 HOWTO (R_V850_TDA_6_8_OFFSET, /* type */
254 1, /* size (0 = byte, 1 = short, 2 = long) */
256 false, /* pc_relative */
258 complain_overflow_dont, /* complain_on_overflow */
259 v850_elf_reloc, /* special_function */
260 "R_V850_TDA_6_8_OFFSET", /* name */
261 false, /* partial_inplace */
264 false), /* pcrel_offset */
266 /* 8 bit offset from the tiny data area pointer. */
267 HOWTO (R_V850_TDA_7_8_OFFSET, /* type */
269 1, /* size (0 = byte, 1 = short, 2 = long) */
271 false, /* pc_relative */
273 complain_overflow_dont, /* complain_on_overflow */
274 v850_elf_reloc, /* special_function */
275 "R_V850_TDA_7_8_OFFSET", /* name */
276 false, /* partial_inplace */
279 false), /* pcrel_offset */
281 /* 7 bit offset from the tiny data area pointer. */
282 HOWTO (R_V850_TDA_7_7_OFFSET, /* type */
284 1, /* size (0 = byte, 1 = short, 2 = long) */
286 false, /* pc_relative */
288 complain_overflow_dont, /* complain_on_overflow */
289 v850_elf_reloc, /* special_function */
290 "R_V850_TDA_7_7_OFFSET", /* name */
291 false, /* partial_inplace */
294 false), /* pcrel_offset */
296 /* start-sanitize-v850e */
298 /* 5 bit offset from the tiny data area pointer. */
299 HOWTO (R_V850_TDA_4_5_OFFSET, /* type */
301 1, /* size (0 = byte, 1 = short, 2 = long) */
303 false, /* pc_relative */
305 complain_overflow_dont, /* complain_on_overflow */
306 v850_elf_reloc, /* special_function */
307 "R_V850_TDA_4_5_OFFSET", /* name */
308 false, /* partial_inplace */
311 false), /* pcrel_offset */
313 /* 4 bit offset from the tiny data area pointer. */
314 HOWTO (R_V850_TDA_4_4_OFFSET, /* type */
316 1, /* size (0 = byte, 1 = short, 2 = long) */
318 false, /* pc_relative */
320 complain_overflow_dont, /* complain_on_overflow */
321 v850_elf_reloc, /* special_function */
322 "R_V850_TDA_4_4_OFFSET", /* name */
323 false, /* partial_inplace */
326 false), /* pcrel_offset */
328 /* 16 bit offset from the short data area pointer. */
329 HOWTO (R_V850_SDA_16_16_SPLIT_OFFSET, /* type */
331 2, /* size (0 = byte, 1 = short, 2 = long) */
333 false, /* pc_relative */
335 complain_overflow_dont, /* complain_on_overflow */
336 v850_elf_reloc, /* special_function */
337 "R_V850_SDA_16_16_SPLIT_OFFSET",/* name */
338 false, /* partial_inplace */
339 0xfffe0020, /* src_mask */
340 0xfffe0020, /* dst_mask */
341 false), /* pcrel_offset */
343 /* 16 bit offset from the zero data area pointer. */
344 HOWTO (R_V850_ZDA_16_16_SPLIT_OFFSET, /* type */
346 2, /* size (0 = byte, 1 = short, 2 = long) */
348 false, /* pc_relative */
350 complain_overflow_dont, /* complain_on_overflow */
351 v850_elf_reloc, /* special_function */
352 "R_V850_ZDA_16_16_SPLIT_OFFSET",/* name */
353 false, /* partial_inplace */
354 0xfffe0020, /* src_mask */
355 0xfffe0020, /* dst_mask */
356 false), /* pcrel_offset */
358 /* end-sanitize-v850e */
361 /* Map BFD reloc types to V850 ELF reloc types. */
363 struct v850_elf_reloc_map
365 unsigned char bfd_reloc_val;
366 unsigned char elf_reloc_val;
369 static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
371 { BFD_RELOC_NONE, R_V850_NONE },
372 { BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL },
373 { BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL },
374 { BFD_RELOC_HI16_S, R_V850_HI16_S },
375 { BFD_RELOC_HI16, R_V850_HI16 },
376 { BFD_RELOC_LO16, R_V850_LO16 },
377 { BFD_RELOC_32, R_V850_32 },
378 { BFD_RELOC_16, R_V850_16 },
379 { BFD_RELOC_8, R_V850_8 },
380 { BFD_RELOC_V850_SDA_16_16_OFFSET, R_V850_SDA_16_16_OFFSET },
381 { BFD_RELOC_V850_SDA_15_16_OFFSET, R_V850_SDA_15_16_OFFSET },
382 { BFD_RELOC_V850_ZDA_16_16_OFFSET, R_V850_ZDA_16_16_OFFSET },
383 { BFD_RELOC_V850_ZDA_15_16_OFFSET, R_V850_ZDA_15_16_OFFSET },
384 { BFD_RELOC_V850_TDA_6_8_OFFSET, R_V850_TDA_6_8_OFFSET },
385 { BFD_RELOC_V850_TDA_7_8_OFFSET, R_V850_TDA_7_8_OFFSET },
386 { BFD_RELOC_V850_TDA_7_7_OFFSET, R_V850_TDA_7_7_OFFSET },
387 /* start-sanitize-v850e */
388 { BFD_RELOC_V850_TDA_4_5_OFFSET, R_V850_TDA_4_5_OFFSET },
389 { BFD_RELOC_V850_TDA_4_4_OFFSET, R_V850_TDA_4_4_OFFSET },
390 { BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, R_V850_SDA_16_16_SPLIT_OFFSET },
391 { BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, R_V850_ZDA_16_16_SPLIT_OFFSET },
392 /* end-sanitize-v850e */
396 /* Map a bfd relocation into the appropriate howto structure */
397 static reloc_howto_type *
398 v850_elf_reloc_type_lookup (abfd, code)
400 bfd_reloc_code_real_type code;
405 i < sizeof (v850_elf_reloc_map) / sizeof (struct v850_elf_reloc_map);
408 if (v850_elf_reloc_map[i].bfd_reloc_val == code)
410 BFD_ASSERT (v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val].type == v850_elf_reloc_map[i].elf_reloc_val);
412 return & v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val];
420 /* Set the howto pointer for an V850 ELF reloc. */
422 v850_elf_info_to_howto_rel (abfd, cache_ptr, dst)
425 Elf32_Internal_Rel *dst;
429 r_type = ELF32_R_TYPE (dst->r_info);
430 BFD_ASSERT (r_type < (unsigned int) R_V850_max);
431 cache_ptr->howto = &v850_elf_howto_table[r_type];
435 /* Look through the relocs for a section during the first phase, and
436 allocate space in the global offset table or procedure linkage
440 v850_elf_check_relocs (abfd, info, sec, relocs)
442 struct bfd_link_info *info;
444 const Elf_Internal_Rela *relocs;
448 Elf_Internal_Shdr *symtab_hdr;
449 struct elf_link_hash_entry **sym_hashes;
450 const Elf_Internal_Rela *rel;
451 const Elf_Internal_Rela *rel_end;
453 enum reloc_type r_type;
455 const char *common = (const char *)0;
457 if (info->relocateable)
461 fprintf (stderr, "v850_elf_check_relocs called for section %s in %s\n",
462 bfd_get_section_name (abfd, sec),
463 bfd_get_filename (abfd));
466 dynobj = elf_hash_table (info)->dynobj;
467 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
468 sym_hashes = elf_sym_hashes (abfd);
471 rel_end = relocs + sec->reloc_count;
472 for (rel = relocs; rel < rel_end; rel++)
474 unsigned long r_symndx;
475 struct elf_link_hash_entry *h;
477 r_symndx = ELF32_R_SYM (rel->r_info);
478 if (r_symndx < symtab_hdr->sh_info)
481 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
483 r_type = (enum reloc_type) ELF32_R_TYPE (rel->r_info);
489 case R_V850_22_PCREL:
498 /* start-sanitize-v850e */
499 case R_V850_SDA_16_16_SPLIT_OFFSET:
500 /* end-sanitize-v850e */
501 case R_V850_SDA_16_16_OFFSET:
502 case R_V850_SDA_15_16_OFFSET:
503 other = V850_OTHER_SDA;
505 goto small_data_common;
507 /* start-sanitize-v850e */
508 case R_V850_ZDA_16_16_SPLIT_OFFSET:
509 /* end-sanitize-v850e */
510 case R_V850_ZDA_16_16_OFFSET:
511 case R_V850_ZDA_15_16_OFFSET:
512 other = V850_OTHER_ZDA;
514 goto small_data_common;
516 /* start-sanitize-v850e */
517 case R_V850_TDA_4_5_OFFSET:
518 case R_V850_TDA_4_4_OFFSET:
519 /* end-sanitize-v850e */
520 case R_V850_TDA_6_8_OFFSET:
521 case R_V850_TDA_7_8_OFFSET:
522 case R_V850_TDA_7_7_OFFSET:
523 other = V850_OTHER_TDA;
527 #define V850_OTHER_MASK (V850_OTHER_TDA | V850_OTHER_SDA | V850_OTHER_ZDA)
532 h->other |= other; /* flag which type of relocation was used */
533 if ((h->other & V850_OTHER_MASK) != (other & V850_OTHER_MASK)
534 && (h->other & V850_OTHER_ERROR) == 0)
538 switch (h->other & V850_OTHER_MASK)
541 msg = "Variable cannot occupy in multiple small data regions";
543 case V850_OTHER_SDA | V850_OTHER_ZDA | V850_OTHER_TDA:
544 msg = "Variable can only be in one of the small, zero, and tiny data regions";
546 case V850_OTHER_SDA | V850_OTHER_ZDA:
547 msg = "Variable cannot be in both small and zero data regions simultaneously";
549 case V850_OTHER_SDA | V850_OTHER_TDA:
550 msg = "Variable cannot be in both small and tiny data regions simultaneously";
552 case V850_OTHER_ZDA | V850_OTHER_TDA:
553 msg = "Variable cannot be in both zero and tiny data regions simultaneously";
557 (*info->callbacks->warning) (info, msg, h->root.root.string,
558 abfd, h->root.u.def.section, 0);
560 bfd_set_error (bfd_error_bad_value);
561 h->other |= V850_OTHER_ERROR;
566 if (h && h->root.type == bfd_link_hash_common
568 && !strcmp (bfd_get_section_name (abfd, h->root.u.c.p->section), "COMMON"))
570 asection *section = h->root.u.c.p->section = bfd_make_section_old_way (abfd, common);
571 section->flags |= SEC_IS_COMMON;
575 fprintf (stderr, "v850_elf_check_relocs, found %s relocation for %s%s\n",
576 v850_elf_howto_table[ (int)r_type ].name,
577 (h && h->root.root.string) ? h->root.root.string : "<unknown>",
578 (h->root.type == bfd_link_hash_common) ? ", symbol is common" : "");
588 /* Insert the addend into the instruction. */
589 static bfd_reloc_status_type
590 v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
603 /* If there is an output BFD,
604 and the symbol is not a section name (which is only defined at final link time),
605 and either we are not putting the addend into the instruction
606 or the addend is zero, so there is nothing to add into the instruction
607 then just fixup the address and return. */
608 if (obfd != (bfd *) NULL
609 && (symbol->flags & BSF_SECTION_SYM) == 0
610 && (! reloc->howto->partial_inplace
611 || reloc->addend == 0))
613 reloc->address += isection->output_offset;
617 else if (obfd != NULL)
619 return bfd_reloc_continue;
623 /* Catch relocs involving undefined symbols. */
624 if (bfd_is_und_section (symbol->section)
625 && (symbol->flags & BSF_WEAK) == 0
627 return bfd_reloc_undefined;
629 /* We handle final linking of some relocs ourselves. */
631 /* Is the address of the relocation really within the section? */
632 if (reloc->address > isection->_cooked_size)
633 return bfd_reloc_outofrange;
635 /* Work out which section the relocation is targetted at and the
636 initial relocation command value. */
638 /* Get symbol value. (Common symbols are special.) */
639 if (bfd_is_com_section (symbol->section))
642 relocation = symbol->value;
644 /* Convert input-section-relative symbol value to absolute + addend. */
645 relocation += symbol->section->output_section->vma;
646 relocation += symbol->section->output_offset;
647 relocation += reloc->addend;
649 if (reloc->howto->pc_relative == true)
651 /* Here the variable relocation holds the final address of the
652 symbol we are relocating against, plus any addend. */
653 relocation -= isection->output_section->vma + isection->output_offset;
655 /* Deal with pcrel_offset */
656 relocation -= reloc->address;
659 /* I've got no clue... */
662 switch (reloc->howto->type)
665 /* fprintf (stderr, "reloc type %d not SUPPORTED\n", reloc->howto->type ); */
666 return bfd_reloc_notsupported;
668 case R_V850_22_PCREL:
669 if (relocation > 0x1ffff || relocation < -0x200000)
670 return bfd_reloc_overflow;
672 if ((relocation % 2) != 0)
673 return bfd_reloc_dangerous;
675 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
677 insn |= (((relocation & 0xfffe) << 16)
678 | ((relocation & 0x3f0000) >> 16));
679 bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
683 if (relocation > 0xff || relocation < -0x100)
684 return bfd_reloc_overflow;
686 if ((relocation % 2) != 0)
687 return bfd_reloc_dangerous;
689 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
691 insn |= ((relocation & 0x1f0) << 7) | ((relocation & 0x0e) << 3);
692 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
696 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
697 relocation = (relocation >> 16) + ((relocation & 0x8000) != 0);
698 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
702 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
703 relocation = (relocation >> 16);
704 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
708 relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
709 /* Do not complain if value has top bit set, as this has been anticipated. */
710 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
714 relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
717 case R_V850_SDA_16_16_OFFSET:
718 case R_V850_ZDA_16_16_OFFSET:
719 if ((long)relocation > 0x7fff || (long)relocation < -0x8000)
720 return bfd_reloc_overflow;
721 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
724 case R_V850_SDA_15_16_OFFSET:
725 case R_V850_ZDA_15_16_OFFSET:
726 if ((long)relocation > 0x7ffe || (long)relocation < -0x8000)
727 return bfd_reloc_overflow;
730 return bfd_reloc_dangerous;
732 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
734 insn |= (relocation >> 1) & ~1;
736 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
739 case R_V850_TDA_6_8_OFFSET:
740 if ((long) relocation > 0xfc || (long) relocation < 0)
741 return bfd_reloc_overflow;
744 return bfd_reloc_dangerous;
746 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
748 insn |= (relocation >> 1);
750 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
753 case R_V850_TDA_7_8_OFFSET:
754 if ((long) relocation > 0xfe || (long) relocation < 0)
755 return bfd_reloc_overflow;
758 return bfd_reloc_dangerous;
760 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
762 insn |= (relocation >> 1);
764 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
767 case R_V850_TDA_7_7_OFFSET:
768 if ((long) relocation > 0x7f || (long) relocation < 0)
769 return bfd_reloc_overflow;
771 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
775 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
778 /* start-sanitize-v850e */
779 case R_V850_TDA_4_5_OFFSET:
780 if ((long) relocation > 0x1e || (long) relocation < 0)
781 return bfd_reloc_overflow;
784 return bfd_reloc_dangerous;
786 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
788 insn |= (relocation >> 1);
790 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
793 case R_V850_TDA_4_4_OFFSET:
794 if ((long) relocation > 0xf || (long) relocation < 0)
795 return bfd_reloc_overflow;
797 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
801 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
804 case R_V850_ZDA_16_16_SPLIT_OFFSET:
805 case R_V850_SDA_16_16_SPLIT_OFFSET:
806 if ((long) relocation > 0xffff || (long) relocation < 0)
807 return bfd_reloc_overflow;
809 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
812 insn |= (relocation & 1) << 5;
813 insn |= (relocation & ~1) << 16;
815 bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
817 /* end-sanitize-v850e */
820 return bfd_reloc_continue;
826 v850_elf_is_local_label_name (abfd, name)
830 return ((name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
831 || (name[0] == '_' && name[1] == '.' && name[2] == 'L'
836 /* Perform a relocation as part of a final link. */
837 static bfd_reloc_status_type
838 v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
839 input_section, contents, offset, value,
840 addend, info, sym_sec, is_local)
841 reloc_howto_type * howto;
844 asection * input_section;
849 struct bfd_link_info * info;
854 unsigned long r_type = howto->type;
855 bfd_byte * hit_data = contents + offset;
860 value -= (input_section->output_section->vma
861 + input_section->output_offset);
864 if ((long)value > 0xff || (long)value < -0x100)
865 return bfd_reloc_overflow;
867 if ((value % 2) != 0)
868 return bfd_reloc_dangerous;
870 insn = bfd_get_16 (input_bfd, hit_data);
872 insn |= ((value & 0x1f0) << 7) | ((value & 0x0e) << 3);
873 bfd_put_16 (input_bfd, insn, hit_data);
876 case R_V850_22_PCREL:
877 value -= (input_section->output_section->vma
878 + input_section->output_offset);
881 if ((long)value > 0x1ffff || (long)value < -0x200000)
882 return bfd_reloc_overflow;
884 if ((value % 2) != 0)
885 return bfd_reloc_dangerous;
887 insn = bfd_get_32 (input_bfd, hit_data);
889 insn |= (((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16));
890 bfd_put_32 (input_bfd, insn, hit_data);
894 value += (short)bfd_get_16 (input_bfd, hit_data);
895 value = (value >> 16) + ((value & 0x8000) != 0);
897 if ((long)value > 0x7fff || (long)value < -0x8000)
898 return bfd_reloc_overflow;
900 bfd_put_16 (input_bfd, value, hit_data);
904 value += (short)bfd_get_16 (input_bfd, hit_data);
907 if ((long)value > 0x7fff || (long)value < -0x8000)
908 return bfd_reloc_overflow;
910 bfd_put_16 (input_bfd, value, hit_data);
914 value += (short)bfd_get_16 (input_bfd, hit_data);
917 bfd_put_16 (input_bfd, value, hit_data);
921 value += (short) bfd_get_16 (input_bfd, hit_data);
923 if ((long) value > 0x7fff || (long) value < -0x8000)
924 return bfd_reloc_overflow;
926 bfd_put_16 (input_bfd, value, hit_data);
929 case R_V850_ZDA_16_16_OFFSET:
930 value -= sym_sec->output_section->vma;
931 value += (short) bfd_get_16 (input_bfd, hit_data);
933 if ((long) value > 0x7fff || (long) value < -0x8000)
934 return bfd_reloc_overflow;
936 bfd_put_16 (input_bfd, value, hit_data);
939 case R_V850_ZDA_15_16_OFFSET:
940 insn = bfd_get_16 (input_bfd, hit_data);
942 value -= sym_sec->output_section->vma;
943 value += ((insn & 0xfffe) << 1);
945 if ((long) value > 0x7ffe || (long) value < -0x8000)
946 return bfd_reloc_overflow;
951 bfd_put_16 (input_bfd, value, hit_data);
955 value += bfd_get_32 (input_bfd, hit_data);
956 bfd_put_32 (input_bfd, value, hit_data);
960 value += (char)bfd_get_8 (input_bfd, hit_data);
962 if ((long)value > 0x7f || (long)value < -0x80)
963 return bfd_reloc_overflow;
965 bfd_put_8 (input_bfd, value, hit_data);
968 case R_V850_SDA_16_16_OFFSET:
971 struct bfd_link_hash_entry * h;
973 /* Get the value of __gp. */
974 h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
975 if (h == (struct bfd_link_hash_entry *) NULL
976 || h->type != bfd_link_hash_defined)
977 return bfd_reloc_other;
980 + h->u.def.section->output_section->vma
981 + h->u.def.section->output_offset);
983 value -= sym_sec->output_section->vma;
984 value -= (gp - sym_sec->output_section->vma);
985 value += (short) bfd_get_16 (input_bfd, hit_data);
987 if ((long)value > 0x7fff || (long)value < -0x8000)
988 return bfd_reloc_overflow;
990 bfd_put_16 (input_bfd, value, hit_data);
994 case R_V850_SDA_15_16_OFFSET:
997 struct bfd_link_hash_entry * h;
999 /* Get the value of __gp. */
1000 h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
1001 if (h == (struct bfd_link_hash_entry *) NULL
1002 || h->type != bfd_link_hash_defined)
1003 return bfd_reloc_other;
1005 gp = (h->u.def.value
1006 + h->u.def.section->output_section->vma
1007 + h->u.def.section->output_offset);
1009 value -= sym_sec->output_section->vma;
1010 value -= (gp - sym_sec->output_section->vma);
1012 insn = bfd_get_16 (input_bfd, hit_data);
1014 value += ((insn & 0xfffe) << 1);
1016 if ((long)value > 0x7ffe || (long)value < -0x8000)
1017 return bfd_reloc_overflow;
1020 value |= (insn & 1);
1022 bfd_put_16 (input_bfd, value, hit_data);
1023 return bfd_reloc_ok;
1026 case R_V850_TDA_6_8_OFFSET:
1029 struct bfd_link_hash_entry * h;
1031 insn = bfd_get_16 (input_bfd, hit_data);
1033 /* Get the value of __ep. */
1034 h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1035 if (h == (struct bfd_link_hash_entry *) NULL
1036 || h->type != bfd_link_hash_defined)
1037 return bfd_reloc_continue; /* Actually this indicates that __ep could not be found. */
1039 ep = (h->u.def.value
1040 + h->u.def.section->output_section->vma
1041 + h->u.def.section->output_offset);
1044 value += ((insn & 0x7e) << 2);
1046 if ((long) value > 0xfc || (long) value < 0)
1047 return bfd_reloc_overflow;
1049 if ((value % 2) != 0)
1050 return bfd_reloc_dangerous;
1053 insn |= (value >> 1);
1055 bfd_put_16 (input_bfd, insn, hit_data);
1056 return bfd_reloc_ok;
1059 case R_V850_TDA_7_8_OFFSET:
1062 struct bfd_link_hash_entry * h;
1064 insn = bfd_get_16 (input_bfd, hit_data);
1066 /* Get the value of __ep. */
1067 h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1068 if (h == (struct bfd_link_hash_entry *) NULL
1069 || h->type != bfd_link_hash_defined)
1070 return bfd_reloc_continue; /* Actually this indicates that __ep could not be found. */
1072 ep = (h->u.def.value
1073 + h->u.def.section->output_section->vma
1074 + h->u.def.section->output_offset);
1077 value += ((insn & 0x7f) << 1);
1079 if ((long) value > 0xfe || (long) value < 0)
1080 return bfd_reloc_overflow;
1083 insn |= (value >> 1);
1085 bfd_put_16 (input_bfd, insn, hit_data);
1086 return bfd_reloc_ok;
1089 case R_V850_TDA_7_7_OFFSET:
1092 struct bfd_link_hash_entry * h;
1094 insn = bfd_get_16 (input_bfd, hit_data);
1096 /* Get the value of __ep. */
1097 h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1098 if (h == (struct bfd_link_hash_entry *) NULL
1099 || h->type != bfd_link_hash_defined)
1100 return bfd_reloc_continue; /* Actually this indicates that __ep could not be found. */
1102 ep = (h->u.def.value
1103 + h->u.def.section->output_section->vma
1104 + h->u.def.section->output_offset);
1107 value += insn & 0x7f;
1109 if ((long) value > 0x7f || (long) value < 0)
1110 return bfd_reloc_overflow;
1114 bfd_put_16 (input_bfd, insn, hit_data);
1115 return bfd_reloc_ok;
1118 /* start-sanitize-v850e */
1119 case R_V850_TDA_4_5_OFFSET:
1122 struct bfd_link_hash_entry * h;
1124 /* Get the value of __ep. */
1125 h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1126 if (h == (struct bfd_link_hash_entry *) NULL
1127 || h->type != bfd_link_hash_defined)
1128 return bfd_reloc_continue; /* Actually this indicates that __ep could not be found. */
1130 ep = (h->u.def.value
1131 + h->u.def.section->output_section->vma
1132 + h->u.def.section->output_offset);
1135 insn = bfd_get_16 (input_bfd, hit_data);
1137 value += ((insn & 0xf) << 1);
1139 if ((long) value > 0x1e || (long) value < 0)
1140 return bfd_reloc_overflow;
1143 insn |= (value >> 1);
1144 bfd_put_16 (input_bfd, insn, hit_data);
1145 return bfd_reloc_ok;
1148 case R_V850_TDA_4_4_OFFSET:
1151 struct bfd_link_hash_entry * h;
1153 /* Get the value of __ep. */
1154 h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1155 if (h == (struct bfd_link_hash_entry *) NULL
1156 || h->type != bfd_link_hash_defined)
1157 return bfd_reloc_continue; /* Actually this indicates that __ep could not be found. */
1159 ep = (h->u.def.value
1160 + h->u.def.section->output_section->vma
1161 + h->u.def.section->output_offset);
1164 insn = bfd_get_16 (input_bfd, hit_data);
1166 value += insn & 0xf;
1168 if ((long) value > 0xf || (long) value < 0)
1169 return bfd_reloc_overflow;
1173 bfd_put_16 (input_bfd, insn, hit_data);
1174 return bfd_reloc_ok;
1177 case R_V850_SDA_16_16_SPLIT_OFFSET:
1180 struct bfd_link_hash_entry * h;
1182 /* Get the value of __gp. */
1183 h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
1184 if (h == (struct bfd_link_hash_entry *) NULL
1185 || h->type != bfd_link_hash_defined)
1186 return bfd_reloc_other;
1188 gp = (h->u.def.value
1189 + h->u.def.section->output_section->vma
1190 + h->u.def.section->output_offset);
1192 value -= sym_sec->output_section->vma;
1193 value -= (gp - sym_sec->output_section->vma);
1195 insn = bfd_get_32 (input_bfd, hit_data);
1197 value += ((insn & 0xfffe0000) >> 16);
1198 value += ((insn & 0x20) >> 5);
1200 if ((long)value > 0x7fff || (long)value < -0x8000)
1201 return bfd_reloc_overflow;
1204 insn |= (value & 1) << 5;
1205 insn |= (value & ~1) << 16;
1207 bfd_put_32 (input_bfd, insn, hit_data);
1208 return bfd_reloc_ok;
1211 case R_V850_ZDA_16_16_SPLIT_OFFSET:
1212 insn = bfd_get_32 (input_bfd, hit_data);
1214 value -= sym_sec->output_section->vma;
1215 value += ((insn & 0xfffe0000) >> 16);
1216 value += ((insn & 0x20) >> 5);
1218 if ((long)value > 0x7fff || (long)value < -0x8000)
1219 return bfd_reloc_overflow;
1222 insn |= (value & 1) << 5;
1223 insn |= (value & ~1) << 16;
1225 bfd_put_32 (input_bfd, insn, hit_data);
1226 return bfd_reloc_ok;
1228 /* end-sanitize-v850e */
1232 return bfd_reloc_ok;
1235 return bfd_reloc_notsupported;
1240 /* Relocate an V850 ELF section. */
1242 v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
1243 contents, relocs, local_syms, local_sections)
1245 struct bfd_link_info * info;
1247 asection * input_section;
1248 bfd_byte * contents;
1249 Elf_Internal_Rela * relocs;
1250 Elf_Internal_Sym * local_syms;
1251 asection ** local_sections;
1253 Elf_Internal_Shdr * symtab_hdr;
1254 struct elf_link_hash_entry ** sym_hashes;
1255 Elf_Internal_Rela * rel;
1256 Elf_Internal_Rela * relend;
1258 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1259 sym_hashes = elf_sym_hashes (input_bfd);
1262 relend = relocs + input_section->reloc_count;
1263 for (; rel < relend; rel++)
1266 reloc_howto_type * howto;
1267 unsigned long r_symndx;
1268 Elf_Internal_Sym * sym;
1270 struct elf_link_hash_entry * h;
1272 bfd_reloc_status_type r;
1274 r_symndx = ELF32_R_SYM (rel->r_info);
1275 r_type = ELF32_R_TYPE (rel->r_info);
1276 howto = v850_elf_howto_table + r_type;
1278 if (info->relocateable)
1280 /* This is a relocateable link. We don't have to change
1281 anything, unless the reloc is against a section symbol,
1282 in which case we have to adjust according to where the
1283 section symbol winds up in the output section. */
1284 if (r_symndx < symtab_hdr->sh_info)
1286 sym = local_syms + r_symndx;
1287 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
1289 sec = local_sections[r_symndx];
1290 rel->r_addend += sec->output_offset + sym->st_value;
1297 /* This is a final link. */
1301 if (r_symndx < symtab_hdr->sh_info)
1303 sym = local_syms + r_symndx;
1304 sec = local_sections[r_symndx];
1305 relocation = (sec->output_section->vma
1306 + sec->output_offset
1311 name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name);
1312 name = (name == NULL) ? "<none>" : name;
1313 fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x rel %x\n", sec->name, name, sym->st_name,
1314 sec->output_section->vma, sec->output_offset, sym->st_value, rel->r_addend, rel);
1320 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
1322 while (h->root.type == bfd_link_hash_indirect
1323 || h->root.type == bfd_link_hash_warning)
1324 h = (struct elf_link_hash_entry *) h->root.u.i.link;
1326 if (h->root.type == bfd_link_hash_defined
1327 || h->root.type == bfd_link_hash_defweak)
1329 sec = h->root.u.def.section;
1330 relocation = (h->root.u.def.value
1331 + sec->output_section->vma
1332 + sec->output_offset);
1334 else if (h->root.type == bfd_link_hash_undefweak)
1338 if (! ((*info->callbacks->undefined_symbol)
1339 (info, h->root.root.string, input_bfd,
1340 input_section, rel->r_offset)))
1346 /* FIXME: We should use the addend, but the COFF relocations
1348 r = v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
1350 contents, rel->r_offset,
1351 relocation, rel->r_addend,
1352 info, sec, h == NULL);
1354 if (r != bfd_reloc_ok)
1357 const char * msg = (const char *)0;
1360 name = h->root.root.string;
1363 name = (bfd_elf_string_from_elf_section
1364 (input_bfd, symtab_hdr->sh_link, sym->st_name));
1365 if (name == NULL || *name == '\0')
1366 name = bfd_section_name (input_bfd, sec);
1371 case bfd_reloc_overflow:
1372 if (! ((*info->callbacks->reloc_overflow)
1373 (info, name, howto->name, (bfd_vma) 0,
1374 input_bfd, input_section, rel->r_offset)))
1378 case bfd_reloc_undefined:
1379 fprintf (stderr, "undef2 %s\n", name );
1380 if (! ((*info->callbacks->undefined_symbol)
1381 (info, name, input_bfd, input_section,
1386 case bfd_reloc_outofrange:
1387 msg = "internal error: out of range error";
1390 case bfd_reloc_notsupported:
1391 msg = "internal error: unsupported relocation error";
1394 case bfd_reloc_dangerous:
1395 msg = "internal error: dangerous relocation";
1398 case bfd_reloc_other:
1399 msg = "could not locate special linker symbol __gp";
1402 case bfd_reloc_continue:
1403 msg = "could not locate special linker symbol __ep";
1407 msg = "internal error: unknown error";
1411 if (!((*info->callbacks->warning)
1412 (info, msg, name, input_bfd, input_section,
1423 /* Set the right machine number. */
1425 v850_elf_object_p (abfd)
1428 switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
1431 case E_V850_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, 0); break;
1432 /* start-sanitize-v850e */
1433 case E_V850E_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); break;
1434 /* end-sanitize-v850e */
1435 /* start-sanitize-v850eq */
1436 case E_V850EQ_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850eq); break;
1437 /* end-sanitize-v850eq */
1441 /* Store the machine number in the flags field. */
1443 v850_elf_final_write_processing (abfd, linker)
1449 switch (bfd_get_mach (abfd))
1452 case 0: val = E_V850_ARCH; break;
1453 /* start-sanitize-v850e */
1454 case bfd_mach_v850e: val = E_V850E_ARCH; break;
1455 /* end-sanitize-v850e */
1456 /* start-sanitize-v850eq */
1457 case bfd_mach_v850eq: val = E_V850EQ_ARCH; break;
1458 /* end-sanitize-v850eq */
1461 elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH;
1462 elf_elfheader (abfd)->e_flags |= val;
1465 /* Function to keep V850 specific file flags. */
1467 v850_elf_set_private_flags (abfd, flags)
1471 BFD_ASSERT (!elf_flags_init (abfd)
1472 || elf_elfheader (abfd)->e_flags == flags);
1474 elf_elfheader (abfd)->e_flags = flags;
1475 elf_flags_init (abfd) = true;
1479 /* Copy backend specific data from one object module to another */
1481 v850_elf_copy_private_bfd_data (ibfd, obfd)
1485 if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1486 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1489 BFD_ASSERT (!elf_flags_init (obfd)
1490 || (elf_elfheader (obfd)->e_flags
1491 == elf_elfheader (ibfd)->e_flags));
1493 elf_gp (obfd) = elf_gp (ibfd);
1494 elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
1495 elf_flags_init (obfd) = true;
1499 /* Merge backend specific data from an object file to the output
1500 object file when linking. */
1502 v850_elf_merge_private_bfd_data (ibfd, obfd)
1509 if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1510 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1513 new_flags = elf_elfheader (ibfd)->e_flags;
1514 old_flags = elf_elfheader (obfd)->e_flags;
1516 if (! elf_flags_init (obfd))
1518 elf_flags_init (obfd) = true;
1519 elf_elfheader (obfd)->e_flags = new_flags;
1521 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
1522 && bfd_get_arch_info (obfd)->the_default)
1524 return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
1530 /* Check flag compatibility. */
1532 if (new_flags == old_flags)
1535 if ((new_flags & EF_V850_ARCH) != (old_flags & EF_V850_ARCH))
1537 _bfd_error_handler ("%s: Architecture mismatch with previous modules",
1538 bfd_get_filename (ibfd));
1539 bfd_set_error (bfd_error_bad_value);
1545 /* Display the flags field */
1548 v850_elf_print_private_bfd_data (abfd, ptr)
1552 FILE * file = (FILE *) ptr;
1554 BFD_ASSERT (abfd != NULL && ptr != NULL)
1556 fprintf (file, "private flags = %x", elf_elfheader (abfd)->e_flags);
1558 switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
1561 case E_V850_ARCH: fprintf (file, ": v850 architecture"); break;
1562 /* start-sanitize-v850e */
1563 case E_V850E_ARCH: fprintf (file, ": v850e architecture"); break;
1564 /* end-sanitize-v850e */
1565 /* start-sanitize-v850eq */
1566 case E_V850EQ_ARCH: fprintf (file, ": v850eq architecture"); break;
1567 /* end-sanitize-v850eq */
1575 #define TARGET_LITTLE_SYM bfd_elf32_v850_vec
1576 #define TARGET_LITTLE_NAME "elf32-v850"
1577 #define ELF_ARCH bfd_arch_v850
1578 #define ELF_MACHINE_CODE EM_CYGNUS_V850
1579 #define ELF_MAXPAGESIZE 0x1000
1581 #define elf_info_to_howto 0
1582 #define elf_info_to_howto_rel v850_elf_info_to_howto_rel
1583 #define elf_backend_check_relocs v850_elf_check_relocs
1584 #define elf_backend_relocate_section v850_elf_relocate_section
1585 #define elf_backend_object_p v850_elf_object_p
1586 #define elf_backend_final_write_processing v850_elf_final_write_processing
1587 #define bfd_elf32_bfd_is_local_label_name v850_elf_is_local_label_name
1588 #define bfd_elf32_bfd_reloc_type_lookup v850_elf_reloc_type_lookup
1589 #define bfd_elf32_bfd_copy_private_bfd_data v850_elf_copy_private_bfd_data
1590 #define bfd_elf32_bfd_merge_private_bfd_data v850_elf_merge_private_bfd_data
1591 #define bfd_elf32_bfd_set_private_flags v850_elf_set_private_flags
1592 #define bfd_elf32_bfd_print_private_bfd_data v850_elf_print_private_bfd_data
1594 #define elf_symbol_leading_char '_'
1596 #include "elf32-target.h"