0cca799e208b0b60301e501b3d9639a01bccc20b
[binutils-gdb.git] / bfd / elf32-v850.c
1 /* V850-specific support for 32-bit ELF
2 Copyright (C) 1996, 1997 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
21
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. */
24
25
26 #include "bfd.h"
27 #include "sysdep.h"
28 #include "bfdlink.h"
29 #include "libbfd.h"
30 #include "elf-bfd.h"
31 #include "elf/v850.h"
32
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 *,
42 bfd *,
43 asection *,
44 bfd_byte *,
45 Elf_Internal_Rela *,
46 Elf_Internal_Sym *,
47 asection **));
48
49 /* Try to minimize the amount of space occupied by relocation tables
50 on the ROM (not that the ROM won't be swamped by other ELF overhead). */
51 #define USE_REL
52
53 static reloc_howto_type v850_elf_howto_table[] =
54 {
55 /* This reloc does nothing. */
56 HOWTO (R_V850_NONE, /* 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 bfd_elf_generic_reloc, /* special_function */
64 "R_V850_NONE", /* name */
65 false, /* partial_inplace */
66 0, /* src_mask */
67 0, /* dst_mask */
68 false), /* pcrel_offset */
69
70 /* A PC relative 9 bit branch. */
71 HOWTO (R_V850_9_PCREL, /* type */
72 2, /* rightshift */
73 2, /* size (0 = byte, 1 = short, 2 = long) */
74 26, /* bitsize */
75 true, /* pc_relative */
76 0, /* bitpos */
77 complain_overflow_bitfield, /* complain_on_overflow */
78 v850_elf_reloc, /* special_function */
79 "R_V850_9_PCREL", /* name */
80 false, /* partial_inplace */
81 0x00ffffff, /* src_mask */
82 0x00ffffff, /* dst_mask */
83 true), /* pcrel_offset */
84
85 /* A PC relative 16 bit load/store. */
86 HOWTO (R_V850_16_PCREL, /* type */
87 0, /* rightshift */
88 2, /* size (0 = byte, 1 = short, 2 = long) */
89 15, /* bitsize */
90 true, /* pc_relative */
91 17, /* bitpos */
92 complain_overflow_bitfield, /* complain_on_overflow */
93 v850_elf_reloc, /* special_function */
94 "R_V850_16_PCREL", /* name */
95 false, /* partial_inplace */
96 0xfffe0000, /* src_mask */
97 0xfffe0000, /* dst_mask */
98 true), /* pcrel_offset */
99
100 /* A PC relative 22 bit branch. */
101 HOWTO (R_V850_22_PCREL, /* type */
102 2, /* rightshift */
103 2, /* size (0 = byte, 1 = short, 2 = long) */
104 22, /* bitsize */
105 true, /* pc_relative */
106 7, /* bitpos */
107 complain_overflow_signed, /* complain_on_overflow */
108 v850_elf_reloc, /* special_function */
109 "R_V850_22_PCREL", /* name */
110 false, /* partial_inplace */
111 0x07ffff80, /* src_mask */
112 0x07ffff80, /* dst_mask */
113 true), /* pcrel_offset */
114
115 /* High 16 bits of symbol value. */
116 HOWTO (R_V850_HI16_S, /* type */
117 0, /* rightshift */
118 1, /* size (0 = byte, 1 = short, 2 = long) */
119 16, /* bitsize */
120 false, /* pc_relative */
121 0, /* bitpos */
122 complain_overflow_dont, /* complain_on_overflow */
123 v850_elf_reloc, /* special_function */
124 "R_V850_HI16_S", /* name */
125 true, /* partial_inplace */
126 0xffff, /* src_mask */
127 0xffff, /* dst_mask */
128 false), /* pcrel_offset */
129
130 /* High 16 bits of symbol value. */
131 HOWTO (R_V850_HI16, /* type */
132 0, /* rightshift */
133 1, /* size (0 = byte, 1 = short, 2 = long) */
134 16, /* bitsize */
135 false, /* pc_relative */
136 0, /* bitpos */
137 complain_overflow_dont, /* complain_on_overflow */
138 v850_elf_reloc, /* special_function */
139 "R_V850_HI16", /* name */
140 true, /* partial_inplace */
141 0xffff, /* src_mask */
142 0xffff, /* dst_mask */
143 false), /* pcrel_offset */
144
145 /* Low 16 bits of symbol value. */
146 HOWTO (R_V850_LO16, /* type */
147 0, /* rightshift */
148 1, /* size (0 = byte, 1 = short, 2 = long) */
149 16, /* bitsize */
150 false, /* pc_relative */
151 0, /* bitpos */
152 complain_overflow_dont, /* complain_on_overflow */
153 v850_elf_reloc, /* special_function */
154 "R_V850_LO16", /* name */
155 true, /* partial_inplace */
156 0xffff, /* src_mask */
157 0xffff, /* dst_mask */
158 false), /* pcrel_offset */
159
160 /* Simple 32bit reloc. */
161 HOWTO (R_V850_32, /* type */
162 0, /* rightshift */
163 2, /* size (0 = byte, 1 = short, 2 = long) */
164 32, /* bitsize */
165 false, /* pc_relative */
166 0, /* bitpos */
167 complain_overflow_dont, /* complain_on_overflow */
168 bfd_elf_generic_reloc, /* special_function */
169 "R_V850_32", /* name */
170 true, /* partial_inplace */
171 0xffffffff, /* src_mask */
172 0xffffffff, /* dst_mask */
173 false), /* pcrel_offset */
174
175 /* Simple 16bit reloc. */
176 HOWTO (R_V850_16, /* type */
177 0, /* rightshift */
178 1, /* size (0 = byte, 1 = short, 2 = long) */
179 16, /* bitsize */
180 false, /* pc_relative */
181 0, /* bitpos */
182 complain_overflow_dont, /* complain_on_overflow */
183 bfd_elf_generic_reloc, /* special_function */
184 "R_V850_16", /* name */
185 true, /* partial_inplace */
186 0xffff, /* src_mask */
187 0xffff, /* dst_mask */
188 false), /* pcrel_offset */
189
190 /* Simple 8bit reloc. */
191 HOWTO (R_V850_8, /* type */
192 0, /* rightshift */
193 0, /* size (0 = byte, 1 = short, 2 = long) */
194 8, /* bitsize */
195 false, /* pc_relative */
196 0, /* bitpos */
197 complain_overflow_dont, /* complain_on_overflow */
198 bfd_elf_generic_reloc, /* special_function */
199 "R_V850_8", /* name */
200 true, /* partial_inplace */
201 0xff, /* src_mask */
202 0xff, /* dst_mask */
203 false), /* pcrel_offset */
204
205 /* Offset from the short data area pointer. */
206 HOWTO (R_V850_SDA_OFFSET, /* type */
207 0, /* rightshift */
208 1, /* size (0 = byte, 1 = short, 2 = long) */
209 16, /* bitsize */
210 false, /* pc_relative */
211 0, /* bitpos */
212 complain_overflow_dont, /* complain_on_overflow */
213 v850_elf_reloc, /* special_function */
214 "R_V850_SDA_OFFSET", /* name */
215 true, /* partial_inplace */
216 0xffff, /* src_mask */
217 0xffff, /* dst_mask */
218 false), /* pcrel_offset */
219
220 /* Offset from the zero data area pointer. */
221 HOWTO (R_V850_ZDA_OFFSET, /* type */
222 0, /* rightshift */
223 1, /* size (0 = byte, 1 = short, 2 = long) */
224 16, /* bitsize */
225 false, /* pc_relative */
226 0, /* bitpos */
227 complain_overflow_dont, /* complain_on_overflow */
228 v850_elf_reloc, /* special_function */
229 "R_V850_ZDA_OFFSET", /* name */
230 true, /* partial_inplace */
231 0xffff, /* src_mask */
232 0xffff, /* dst_mask */
233 false), /* pcrel_offset */
234
235 /* Offset from the tiny data area pointer. */
236 HOWTO (R_V850_TDA_OFFSET, /* type */
237 0, /* rightshift */
238 2, /* size (0 = byte, 1 = short, 2 = long) */
239 8, /* bitsize */
240 false, /* pc_relative */
241 0, /* bitpos */
242 complain_overflow_dont, /* complain_on_overflow */
243 v850_elf_reloc, /* special_function */
244 "R_V850_TDA_OFFSET", /* name */
245 true, /* partial_inplace */
246 0xff, /* src_mask */
247 0xff, /* dst_mask */
248 false), /* pcrel_offset */
249
250 };
251
252 /* Map BFD reloc types to V850 ELF reloc types. */
253
254 struct v850_elf_reloc_map
255 {
256 unsigned char bfd_reloc_val;
257 unsigned char elf_reloc_val;
258 };
259
260 static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
261 {
262 { BFD_RELOC_NONE, R_V850_NONE, },
263 { BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL, },
264 { BFD_RELOC_V850_16_PCREL, R_V850_16_PCREL, },
265 { BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL, },
266 { BFD_RELOC_HI16_S, R_V850_HI16_S, },
267 { BFD_RELOC_HI16, R_V850_HI16, },
268 { BFD_RELOC_LO16, R_V850_LO16, },
269 { BFD_RELOC_32, R_V850_32, },
270 { BFD_RELOC_16, R_V850_16, },
271 { BFD_RELOC_8, R_V850_8, },
272 { BFD_RELOC_V850_TDA_OFFSET, R_V850_TDA_OFFSET, },
273 { BFD_RELOC_V850_SDA_OFFSET, R_V850_SDA_OFFSET, },
274 { BFD_RELOC_V850_ZDA_OFFSET, R_V850_ZDA_OFFSET, },
275 };
276
277 \f
278 /* Map a bfd relocation into the appropriate howto structure */
279 static reloc_howto_type *
280 v850_elf_reloc_type_lookup (abfd, code)
281 bfd *abfd;
282 bfd_reloc_code_real_type code;
283 {
284 unsigned int i;
285
286 for (i = 0;
287 i < sizeof (v850_elf_reloc_map) / sizeof (struct v850_elf_reloc_map);
288 i++)
289 {
290 if (v850_elf_reloc_map[i].bfd_reloc_val == code)
291 return &v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val];
292 }
293
294 return NULL;
295 }
296
297 \f
298 /* Set the howto pointer for an V850 ELF reloc. */
299 static void
300 v850_elf_info_to_howto_rel (abfd, cache_ptr, dst)
301 bfd *abfd;
302 arelent *cache_ptr;
303 Elf32_Internal_Rel *dst;
304 {
305 unsigned int r_type;
306
307 r_type = ELF32_R_TYPE (dst->r_info);
308 BFD_ASSERT (r_type < (unsigned int) R_V850_max);
309 cache_ptr->howto = &v850_elf_howto_table[r_type];
310 }
311
312 \f
313 /* Look through the relocs for a section during the first phase, and
314 allocate space in the global offset table or procedure linkage
315 table. */
316
317 static boolean
318 v850_elf_check_relocs (abfd, info, sec, relocs)
319 bfd *abfd;
320 struct bfd_link_info *info;
321 asection *sec;
322 const Elf_Internal_Rela *relocs;
323 {
324 boolean ret = true;
325 bfd *dynobj;
326 Elf_Internal_Shdr *symtab_hdr;
327 struct elf_link_hash_entry **sym_hashes;
328 const Elf_Internal_Rela *rel;
329 const Elf_Internal_Rela *rel_end;
330 asection *sreloc;
331 enum reloc_type r_type;
332 int other = 0;
333 const char *common = (const char *)0;
334
335 if (info->relocateable)
336 return true;
337
338 #ifdef DEBUG
339 fprintf (stderr, "v850_elf_check_relocs called for section %s in %s\n",
340 bfd_get_section_name (abfd, sec),
341 bfd_get_filename (abfd));
342 #endif
343
344 dynobj = elf_hash_table (info)->dynobj;
345 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
346 sym_hashes = elf_sym_hashes (abfd);
347 sreloc = NULL;
348
349 rel_end = relocs + sec->reloc_count;
350 for (rel = relocs; rel < rel_end; rel++)
351 {
352 unsigned long r_symndx;
353 struct elf_link_hash_entry *h;
354
355 r_symndx = ELF32_R_SYM (rel->r_info);
356 if (r_symndx < symtab_hdr->sh_info)
357 h = NULL;
358 else
359 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
360
361 r_type = (enum reloc_type) ELF32_R_TYPE (rel->r_info);
362 switch (r_type)
363 {
364 default:
365 case R_V850_NONE:
366 case R_V850_9_PCREL:
367 case R_V850_16_PCREL:
368 case R_V850_22_PCREL:
369 case R_V850_HI16_S:
370 case R_V850_HI16:
371 case R_V850_LO16:
372 case R_V850_32:
373 case R_V850_16:
374 case R_V850_8:
375 break;
376
377 case R_V850_SDA_OFFSET:
378 other = V850_OTHER_SDA;
379 common = ".scommon";
380 goto small_data_common;
381
382 case R_V850_ZDA_OFFSET:
383 other = V850_OTHER_ZDA;
384 common = ".zcommon";
385 goto small_data_common;
386
387 case R_V850_TDA_OFFSET:
388 other = V850_OTHER_TDA;
389 common = ".tcommon";
390 /* fall through */
391
392 #define V850_OTHER_MASK (V850_OTHER_TDA | V850_OTHER_SDA | V850_OTHER_ZDA)
393
394 small_data_common:
395 if (h)
396 {
397 h->other |= other; /* flag which type of relocation was used */
398 if ((h->other & V850_OTHER_MASK) != (other & V850_OTHER_MASK)
399 && (h->other & V850_OTHER_ERROR) == 0)
400 {
401 const char *msg;
402
403 switch (h->other & V850_OTHER_MASK)
404 {
405 default:
406 msg = "Variable cannot occupy in multiple small data regions";
407 break;
408 case V850_OTHER_SDA | V850_OTHER_ZDA | V850_OTHER_TDA:
409 msg = "Variable can only be in one of the small, zero, and tiny data regions";
410 break;
411 case V850_OTHER_SDA | V850_OTHER_ZDA:
412 msg = "Variable cannot be in both small and zero data regions simultaneously";
413 break;
414 case V850_OTHER_SDA | V850_OTHER_TDA:
415 msg = "Variable cannot be in both small and tiny data regions simultaneously";
416 break;
417 case V850_OTHER_ZDA | V850_OTHER_TDA:
418 msg = "Variable cannot be in both zero and tiny data regions simultaneously";
419 break;
420 }
421
422 (*info->callbacks->warning) (info, msg, h->root.root.string,
423 abfd, h->root.u.def.section, 0);
424
425 bfd_set_error (bfd_error_bad_value);
426 h->other |= V850_OTHER_ERROR;
427 ret = false;
428 }
429 }
430
431 if (h && h->root.type == bfd_link_hash_common
432 && h->root.u.c.p
433 && !strcmp (bfd_get_section_name (abfd, h->root.u.c.p->section), "COMMON"))
434 {
435 asection *section = h->root.u.c.p->section = bfd_make_section_old_way (abfd, common);
436 section->flags |= SEC_IS_COMMON;
437 }
438
439 #ifdef DEBUG
440 fprintf (stderr, "v850_elf_check_relocs, found %s relocation for %s%s\n",
441 v850_elf_howto_table[ (int)r_type ].name,
442 (h && h->root.root.string) ? h->root.root.string : "<unknown>",
443 (h->root.type == bfd_link_hash_common) ? ", symbol is common" : "");
444 #endif
445 break;
446 }
447 }
448
449 return ret;
450 }
451
452 \f
453 static bfd_reloc_status_type
454 v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
455 bfd *abfd;
456 arelent *reloc;
457 asymbol *symbol;
458 PTR data;
459 asection *isection;
460 bfd *obfd;
461 char **err;
462 {
463 if (obfd != (bfd *) NULL
464 && (symbol->flags & BSF_SECTION_SYM) == 0
465 && (! reloc->howto->partial_inplace
466 || reloc->addend == 0))
467 {
468 reloc->address += isection->output_offset;
469 return bfd_reloc_ok;
470 }
471 else if (obfd != NULL)
472 {
473 return bfd_reloc_continue;
474 }
475
476 /* Catch relocs involving undefined symbols. */
477 if (bfd_is_und_section (symbol->section)
478 && (symbol->flags & BSF_WEAK) == 0
479 && obfd == NULL)
480 return bfd_reloc_undefined;
481
482 /* We handle final linking of some relocs ourselves. */
483 {
484 long relocation, insn;
485
486 /* Is the address of the relocation really within the section? */
487 if (reloc->address > isection->_cooked_size)
488 return bfd_reloc_outofrange;
489
490 /* Work out which section the relocation is targetted at and the
491 initial relocation command value. */
492
493 /* Get symbol value. (Common symbols are special.) */
494 if (bfd_is_com_section (symbol->section))
495 relocation = 0;
496 else
497 relocation = symbol->value;
498
499 /* Convert input-section-relative symbol value to absolute + addend. */
500 relocation += symbol->section->output_section->vma;
501 relocation += symbol->section->output_offset;
502 relocation += reloc->addend;
503
504 if (reloc->howto->pc_relative == true)
505 {
506 /* Here the variable relocation holds the final address of the
507 symbol we are relocating against, plus any addend. */
508 relocation -= isection->output_section->vma + isection->output_offset;
509
510 /* Deal with pcrel_offset */
511 relocation -= reloc->address;
512 }
513
514 /* I've got no clue... */
515 reloc->addend = 0;
516
517 switch (reloc->howto->type)
518 {
519 default:
520 return bfd_reloc_notsupported;
521
522 case R_V850_22_PCREL:
523 if (relocation > 0x1ffff || relocation < -0x200000)
524 return bfd_reloc_overflow;
525
526 if ((relocation % 2) != 0)
527 return bfd_reloc_dangerous;
528
529 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
530 insn &= ~0xfffe003f;
531 insn |= (((relocation & 0xfffe) << 16)
532 | ((relocation & 0x3f0000) >> 16));
533 bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
534 return bfd_reloc_ok;
535
536 case R_V850_16_PCREL:
537 if (relocation > 0x7fff || relocation < -0x10000)
538 return bfd_reloc_overflow;
539
540 if ((relocation % 2) != 0)
541 return bfd_reloc_dangerous;
542
543 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
544 insn &= 0x1ffff;
545 insn |= ((relocation & 0xfffe) << 16);
546 bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc->address);
547 return bfd_reloc_ok;
548
549 case R_V850_9_PCREL:
550 if (relocation > 0xff || relocation < -0x100)
551 return bfd_reloc_overflow;
552
553 if ((relocation % 2) != 0)
554 return bfd_reloc_dangerous;
555
556 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
557 insn &= ~ 0xf870;
558 insn |= ((relocation & 0x1f0) << 7) | ((relocation & 0x0e) << 3);
559 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
560 return bfd_reloc_ok;
561
562 case R_V850_HI16_S:
563 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
564 relocation = (relocation >> 16) + ((relocation & 0x8000) != 0);
565 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
566 return bfd_reloc_ok;
567
568 case R_V850_HI16:
569 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
570 relocation = (relocation >> 16);
571 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
572 return bfd_reloc_ok;
573
574 case R_V850_16:
575 case R_V850_ZDA_OFFSET:
576 relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
577
578 if ((long)relocation > 0x7fff || (long)relocation < -0x8000)
579 return bfd_reloc_overflow;
580
581 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
582 return bfd_reloc_ok;
583
584 #if 0
585 case R_V850_SDA_OFFSET:
586 {
587 unsigned long gp;
588 struct bfd_link_hash_entry *h;
589
590 relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
591
592 /* Get the value of __gp. */
593 h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
594 if (h == (struct bfd_link_hash_entry *) NULL
595 || h->type != bfd_link_hash_defined)
596 return bfd_reloc_undefined;
597
598 gp = (h->u.def.value
599 + h->u.def.section->output_section->vma
600 + h->u.def.section->output_offset);
601 relocation -= gp;
602
603 if ((long)relocation > 0x7fff || (long)relocation < -0x8000)
604 return bfd_reloc_overflow;
605
606 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
607 return bfd_reloc_ok;
608 }
609 #endif
610 }
611 }
612
613 return bfd_reloc_continue;
614 }
615
616 \f
617 /*ARGSUSED*/
618 static boolean
619 v850_elf_is_local_label_name (abfd, name)
620 bfd *abfd;
621 const char *name;
622 {
623 return ((name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
624 || (name[0] == '_' && name[1] == '.' && name[2] == 'L'
625 && name[3] == '_'));
626 }
627
628 \f
629 /* Perform a relocation as part of a final link. */
630 static bfd_reloc_status_type
631 v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
632 input_section, contents, offset, value,
633 addend, info, sym_sec, is_local)
634 reloc_howto_type *howto;
635 bfd *input_bfd;
636 bfd *output_bfd;
637 asection *input_section;
638 bfd_byte *contents;
639 bfd_vma offset;
640 bfd_vma value;
641 bfd_vma addend;
642 struct bfd_link_info *info;
643 asection *sym_sec;
644 int is_local;
645 {
646 unsigned long insn;
647 unsigned long r_type = howto->type;
648 bfd_byte *hit_data = contents + offset;
649
650 switch (r_type)
651 {
652 case R_V850_9_PCREL:
653 value -= (input_section->output_section->vma
654 + input_section->output_offset);
655 value -= offset;
656
657 if ((long)value > 0xff || (long)value < -0x100)
658 return bfd_reloc_overflow;
659
660 if ((value % 2) != 0)
661 return bfd_reloc_dangerous;
662
663 insn = bfd_get_16 (input_bfd, hit_data);
664 insn &= 0x078f;
665 insn |= ((value & 0x1f0) << 7) | ((value & 0x0e) << 3);
666 bfd_put_16 (input_bfd, insn, hit_data);
667 return bfd_reloc_ok;
668
669 case R_V850_16_PCREL:
670 value -= (input_section->output_section->vma + input_section->output_offset);
671 value -= offset;
672
673 if ((long)value > 0x7fff || (long)value < -0x10000)
674 return bfd_reloc_overflow;
675
676 if ((value % 2) != 0)
677 return bfd_reloc_dangerous;
678
679 insn = bfd_get_32 (input_bfd, hit_data);
680 insn &= 0x1ffff;
681 insn |= ((value & 0xfffe) << 16);
682 bfd_put_32 (input_bfd, insn, hit_data);
683 return bfd_reloc_ok;
684
685 case R_V850_22_PCREL:
686 value -= (input_section->output_section->vma
687 + input_section->output_offset);
688 value -= offset;
689
690 if ((long)value > 0x1ffff || (long)value < -0x200000)
691 return bfd_reloc_overflow;
692
693 if ((value % 2) != 0)
694 return bfd_reloc_dangerous;
695
696 insn = bfd_get_32 (input_bfd, hit_data);
697 insn &= 0x1ffc0;
698 insn |= (((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16));
699 bfd_put_32 (input_bfd, insn, hit_data);
700 return bfd_reloc_ok;
701
702 case R_V850_HI16_S:
703 value += (short)bfd_get_16 (input_bfd, hit_data);
704 value = (value >> 16) + ((value & 0x8000) != 0);
705
706 if ((long)value > 0x7fff || (long)value < -0x8000)
707 return bfd_reloc_overflow;
708
709 bfd_put_16 (input_bfd, value, hit_data);
710 return bfd_reloc_ok;
711
712 case R_V850_HI16:
713 value += (short)bfd_get_16 (input_bfd, hit_data);
714 value >>= 16;
715
716 if ((long)value > 0x7fff || (long)value < -0x8000)
717 return bfd_reloc_overflow;
718
719 bfd_put_16 (input_bfd, value, hit_data);
720 return bfd_reloc_ok;
721
722 case R_V850_LO16:
723 value += (short)bfd_get_16 (input_bfd, hit_data);
724 value &= 0xffff;
725
726 bfd_put_16 (input_bfd, value, hit_data);
727 return bfd_reloc_ok;
728
729 case R_V850_16:
730 case R_V850_ZDA_OFFSET:
731 value += (short)bfd_get_16 (input_bfd, hit_data);
732
733 if ((long)value > 0x7fff || (long)value < -0x8000)
734 return bfd_reloc_overflow;
735
736 bfd_put_16 (input_bfd, value, hit_data);
737 return bfd_reloc_ok;
738
739 case R_V850_32:
740 value += bfd_get_32 (input_bfd, hit_data);
741 bfd_put_32 (input_bfd, value, hit_data);
742 return bfd_reloc_ok;
743
744 case R_V850_8:
745 value += (char)bfd_get_8 (input_bfd, hit_data);
746
747 if ((long)value > 0x7f || (long)value < -0x80)
748 return bfd_reloc_overflow;
749
750 bfd_put_8 (input_bfd, value, hit_data);
751 return bfd_reloc_ok;
752
753 case R_V850_SDA_OFFSET:
754 {
755 unsigned long gp;
756 struct bfd_link_hash_entry *h;
757
758 value += (short)bfd_get_16 (input_bfd, hit_data);
759
760 /* Get the value of __gp. */
761 h = bfd_link_hash_lookup (info->hash, "__gp", false,
762 false, true);
763 if (h == (struct bfd_link_hash_entry *) NULL
764 || h->type != bfd_link_hash_defined)
765 return bfd_reloc_undefined;
766
767 gp = (h->u.def.value
768 + h->u.def.section->output_section->vma
769 + h->u.def.section->output_offset);
770 value -= gp;
771
772 if ((long)value > 0x7fff || (long)value < -0x8000)
773 return bfd_reloc_overflow;
774
775 bfd_put_16 (input_bfd, value, hit_data);
776 return bfd_reloc_ok;
777 }
778
779 case R_V850_TDA_OFFSET:
780 {
781 unsigned long ep;
782 struct bfd_link_hash_entry *h;
783
784 insn = bfd_get_16 (input_bfd, hit_data);
785
786 /* Get the value of __ep. */
787 h = bfd_link_hash_lookup (info->hash, "__ep", false,
788 false, true);
789 if (h == (struct bfd_link_hash_entry *) NULL
790 || h->type != bfd_link_hash_defined)
791 return bfd_reloc_undefined;
792
793 ep = (h->u.def.value
794 + h->u.def.section->output_section->vma
795 + h->u.def.section->output_offset);
796 value -= ep;
797
798
799 /* Overflow computation and operand insertion is complicated
800 by valid offsets and insertions changing depending on the
801 instruction being used! */
802 if ((insn & 0x0780) == 0x0500)
803 {
804 value += ((insn & 0x7f) << 1);
805
806 /* Handle sld.w and sst.w -- 8 bit unsigned offset */
807 if ((long) value > 0xff || (long) value < 0)
808 return bfd_reloc_overflow;
809
810 if ((value % 2) != 0)
811 return bfd_reloc_dangerous;
812
813 insn &= 0xff81;
814 insn |= (value >> 1);
815 bfd_put_16 (input_bfd, insn, hit_data);
816 return bfd_reloc_ok;
817 }
818
819 if ((insn & 0x0780) == 0x0400 || (insn & 0x0780) == 0x0480)
820 {
821 value += ((insn & 0x7f) << 1);
822
823 /* Handle sld.h and sst.h -- 8 bit unsigned offset */
824 if ((long) value > 0xff || (long) value < 0)
825 return bfd_reloc_overflow;
826
827 if ((value % 2) != 0)
828 return bfd_reloc_dangerous;
829
830 insn &= 0xff80;
831 insn |= (value >> 1);
832 bfd_put_16 (input_bfd, insn, hit_data);
833 return bfd_reloc_ok;
834 }
835
836 if ((insn & 0x0780) == 0x0300 || (insn & 0x0780) == 0x0380)
837 {
838 value += (insn & 0x7f);
839
840 /* Handle sld.b and sst.b -- 7 bit unsigned offset */
841 if ((long) value > 0x7f || (long) value < 0)
842 return bfd_reloc_overflow;
843 insn &= 0xff80;
844 insn |= value;
845 bfd_put_16 (input_bfd, insn, hit_data);
846 return bfd_reloc_ok;
847 }
848
849 /* Guess (XXX) that it's a movea instruction or something
850 similar. */
851 value += (short)insn;
852 if ((long)value > 0x7fff || (long)value < -0x8000)
853 return bfd_reloc_overflow;
854
855 bfd_put_16 (input_bfd, value, hit_data);
856 return bfd_reloc_ok;
857 }
858
859 case R_V850_NONE:
860 return bfd_reloc_ok;
861
862 default:
863 return bfd_reloc_notsupported;
864 }
865 }
866
867 \f
868 /* Relocate an V850 ELF section. */
869 static boolean
870 v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
871 contents, relocs, local_syms, local_sections)
872 bfd *output_bfd;
873 struct bfd_link_info *info;
874 bfd *input_bfd;
875 asection *input_section;
876 bfd_byte *contents;
877 Elf_Internal_Rela *relocs;
878 Elf_Internal_Sym *local_syms;
879 asection **local_sections;
880 {
881 Elf_Internal_Shdr *symtab_hdr;
882 struct elf_link_hash_entry **sym_hashes;
883 Elf_Internal_Rela *rel, *relend;
884
885 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
886 sym_hashes = elf_sym_hashes (input_bfd);
887
888 rel = relocs;
889 relend = relocs + input_section->reloc_count;
890 for (; rel < relend; rel++)
891 {
892 int r_type;
893 reloc_howto_type *howto;
894 unsigned long r_symndx;
895 Elf_Internal_Sym *sym;
896 asection *sec;
897 struct elf_link_hash_entry *h;
898 bfd_vma relocation;
899 bfd_reloc_status_type r;
900
901 r_symndx = ELF32_R_SYM (rel->r_info);
902 r_type = ELF32_R_TYPE (rel->r_info);
903 howto = v850_elf_howto_table + r_type;
904
905 if (info->relocateable)
906 {
907 /* This is a relocateable link. We don't have to change
908 anything, unless the reloc is against a section symbol,
909 in which case we have to adjust according to where the
910 section symbol winds up in the output section. */
911 if (r_symndx < symtab_hdr->sh_info)
912 {
913 sym = local_syms + r_symndx;
914 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
915 {
916 sec = local_sections[r_symndx];
917 rel->r_addend += sec->output_offset + sym->st_value;
918 }
919 }
920
921 continue;
922 }
923
924 /* This is a final link. */
925 h = NULL;
926 sym = NULL;
927 sec = NULL;
928 if (r_symndx < symtab_hdr->sh_info)
929 {
930 sym = local_syms + r_symndx;
931 sec = local_sections[r_symndx];
932 relocation = (sec->output_section->vma
933 + sec->output_offset
934 + sym->st_value);
935 }
936 else
937 {
938 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
939 while (h->root.type == bfd_link_hash_indirect
940 || h->root.type == bfd_link_hash_warning)
941 h = (struct elf_link_hash_entry *) h->root.u.i.link;
942 if (h->root.type == bfd_link_hash_defined
943 || h->root.type == bfd_link_hash_defweak)
944 {
945 sec = h->root.u.def.section;
946 relocation = (h->root.u.def.value
947 + sec->output_section->vma
948 + sec->output_offset);
949 }
950 else if (h->root.type == bfd_link_hash_undefweak)
951 relocation = 0;
952 else
953 {
954 if (! ((*info->callbacks->undefined_symbol)
955 (info, h->root.root.string, input_bfd,
956 input_section, rel->r_offset)))
957 return false;
958 relocation = 0;
959 }
960 }
961
962 /* FIXME: We should use the addend, but the COFF relocations
963 don't. */
964 r = v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
965 input_section,
966 contents, rel->r_offset,
967 relocation, rel->r_addend,
968 info, sec, h == NULL);
969
970 if (r != bfd_reloc_ok)
971 {
972 const char *name;
973 const char *msg = (const char *)0;
974
975 if (h != NULL)
976 name = h->root.root.string;
977 else
978 {
979 name = (bfd_elf_string_from_elf_section
980 (input_bfd, symtab_hdr->sh_link, sym->st_name));
981 if (name == NULL || *name == '\0')
982 name = bfd_section_name (input_bfd, sec);
983 }
984
985 switch (r)
986 {
987 case bfd_reloc_overflow:
988 if (! ((*info->callbacks->reloc_overflow)
989 (info, name, howto->name, (bfd_vma) 0,
990 input_bfd, input_section, rel->r_offset)))
991 return false;
992 break;
993
994 case bfd_reloc_undefined:
995 if (! ((*info->callbacks->undefined_symbol)
996 (info, name, input_bfd, input_section,
997 rel->r_offset)))
998 return false;
999 break;
1000
1001 case bfd_reloc_outofrange:
1002 msg = "internal error: out of range error";
1003 goto common_error;
1004
1005 case bfd_reloc_notsupported:
1006 msg = "internal error: unsupported relocation error";
1007 goto common_error;
1008
1009 case bfd_reloc_dangerous:
1010 msg = "internal error: dangerous error";
1011 goto common_error;
1012
1013 default:
1014 msg = "internal error: unknown error";
1015 /* fall through */
1016
1017 common_error:
1018 if (!((*info->callbacks->warning)
1019 (info, msg, name, input_bfd, input_section,
1020 rel->r_offset)))
1021 return false;
1022 break;
1023 }
1024 }
1025 }
1026
1027 return true;
1028 }
1029
1030 /* Set the right machine number. */
1031
1032 static boolean
1033 v850_elf_object_p (abfd)
1034 bfd *abfd;
1035 {
1036 switch (get_elf_backend_data (abfd) -> elf_machine_code)
1037 {
1038 default:
1039 case EM_CYGNUS_V850: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, 0); break;
1040 /* start-sanitize-v850e */
1041 case EM_CYGNUS_V850E: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); break;
1042 /* end-sanitize-v850e */
1043 /* start-sanitize-v850eq */
1044 case EM_CYGNUS_V850EQ: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850eq); break;
1045 /* start-sanitize-v850eq */
1046 }
1047 }
1048
1049 \f
1050 #define TARGET_LITTLE_SYM bfd_elf32_v850_vec
1051 #define TARGET_LITTLE_NAME "elf32-v850"
1052 #define ELF_ARCH bfd_arch_v850
1053 #define ELF_MACHINE_CODE EM_CYGNUS_V850
1054 /* start-sanitize-v850e */
1055 #undef ELF_MACHINE_CODE
1056 #define ELF_MACHINE_CODE EM_CYGNUS_V850E
1057 /* end-sanitize-v850e */
1058 /* start-sanitize-v850eq */
1059 #undef ELF_MACHINE_CODE
1060 #define ELF_MACHINE_CODE EM_CYGNUS_V850EQ
1061 /* end-sanitize-v850eq */
1062
1063 #define ELF_MAXPAGESIZE 0x1000
1064
1065 #define elf_info_to_howto 0
1066 #define elf_info_to_howto_rel v850_elf_info_to_howto_rel
1067 #define elf_backend_check_relocs v850_elf_check_relocs
1068 #define elf_backend_relocate_section v850_elf_relocate_section
1069 #define elf_backend_object_p v850_elf_object_p
1070 #define bfd_elf32_bfd_is_local_label_name v850_elf_is_local_label_name
1071 #define bfd_elf32_bfd_reloc_type_lookup v850_elf_reloc_type_lookup
1072
1073 #define elf_symbol_leading_char '_'
1074
1075 #include "elf32-target.h"