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
*,
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). */
53 static reloc_howto_type v850_elf_howto_table
[] =
55 /* This reloc does nothing. */
56 HOWTO (R_V850_NONE
, /* type */
58 2, /* size (0 = byte, 1 = short, 2 = long) */
60 false, /* pc_relative */
62 complain_overflow_bitfield
, /* complain_on_overflow */
63 bfd_elf_generic_reloc
, /* special_function */
64 "R_V850_NONE", /* name */
65 false, /* partial_inplace */
68 false), /* pcrel_offset */
70 /* A PC relative 9 bit branch. */
71 HOWTO (R_V850_9_PCREL
, /* type */
73 2, /* size (0 = byte, 1 = short, 2 = long) */
75 true, /* pc_relative */
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 */
85 /* A PC relative 16 bit load/store. */
86 HOWTO (R_V850_16_PCREL
, /* type */
88 2, /* size (0 = byte, 1 = short, 2 = long) */
90 true, /* pc_relative */
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 */
100 /* A PC relative 22 bit branch. */
101 HOWTO (R_V850_22_PCREL
, /* type */
103 2, /* size (0 = byte, 1 = short, 2 = long) */
105 true, /* pc_relative */
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 */
115 /* High 16 bits of symbol value. */
116 HOWTO (R_V850_HI16_S
, /* type */
118 1, /* size (0 = byte, 1 = short, 2 = long) */
120 false, /* pc_relative */
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 */
130 /* High 16 bits of symbol value. */
131 HOWTO (R_V850_HI16
, /* type */
133 1, /* size (0 = byte, 1 = short, 2 = long) */
135 false, /* pc_relative */
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 */
145 /* Low 16 bits of symbol value. */
146 HOWTO (R_V850_LO16
, /* type */
148 1, /* size (0 = byte, 1 = short, 2 = long) */
150 false, /* pc_relative */
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 */
160 /* Simple 32bit reloc. */
161 HOWTO (R_V850_32
, /* type */
163 2, /* size (0 = byte, 1 = short, 2 = long) */
165 false, /* pc_relative */
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 */
175 /* Simple 16bit reloc. */
176 HOWTO (R_V850_16
, /* type */
178 1, /* size (0 = byte, 1 = short, 2 = long) */
180 false, /* pc_relative */
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 */
190 /* Simple 8bit reloc. */
191 HOWTO (R_V850_8
, /* type */
193 0, /* size (0 = byte, 1 = short, 2 = long) */
195 false, /* pc_relative */
197 complain_overflow_dont
, /* complain_on_overflow */
198 bfd_elf_generic_reloc
, /* special_function */
199 "R_V850_8", /* name */
200 true, /* partial_inplace */
203 false), /* pcrel_offset */
205 /* Offset from the short data area pointer. */
206 HOWTO (R_V850_SDA_OFFSET
, /* type */
208 1, /* size (0 = byte, 1 = short, 2 = long) */
210 false, /* pc_relative */
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 */
220 /* Offset from the zero data area pointer. */
221 HOWTO (R_V850_ZDA_OFFSET
, /* type */
223 1, /* size (0 = byte, 1 = short, 2 = long) */
225 false, /* pc_relative */
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 */
235 /* Offset from the tiny data area pointer. */
236 HOWTO (R_V850_TDA_OFFSET
, /* type */
238 2, /* size (0 = byte, 1 = short, 2 = long) */
240 false, /* pc_relative */
242 complain_overflow_dont
, /* complain_on_overflow */
243 v850_elf_reloc
, /* special_function */
244 "R_V850_TDA_OFFSET", /* name */
245 true, /* partial_inplace */
248 false), /* pcrel_offset */
252 /* Map BFD reloc types to V850 ELF reloc types. */
254 struct v850_elf_reloc_map
256 unsigned char bfd_reloc_val
;
257 unsigned char elf_reloc_val
;
260 static const struct v850_elf_reloc_map v850_elf_reloc_map
[] =
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
, },
278 /* Map a bfd relocation into the appropriate howto structure */
279 static reloc_howto_type
*
280 v850_elf_reloc_type_lookup (abfd
, code
)
282 bfd_reloc_code_real_type code
;
287 i
< sizeof (v850_elf_reloc_map
) / sizeof (struct v850_elf_reloc_map
);
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
];
298 /* Set the howto pointer for an V850 ELF reloc. */
300 v850_elf_info_to_howto_rel (abfd
, cache_ptr
, dst
)
303 Elf32_Internal_Rel
*dst
;
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
];
313 /* Look through the relocs for a section during the first phase, and
314 allocate space in the global offset table or procedure linkage
318 v850_elf_check_relocs (abfd
, info
, sec
, relocs
)
320 struct bfd_link_info
*info
;
322 const Elf_Internal_Rela
*relocs
;
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
;
331 enum reloc_type r_type
;
333 const char *common
= (const char *)0;
335 if (info
->relocateable
)
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
));
344 dynobj
= elf_hash_table (info
)->dynobj
;
345 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
346 sym_hashes
= elf_sym_hashes (abfd
);
349 rel_end
= relocs
+ sec
->reloc_count
;
350 for (rel
= relocs
; rel
< rel_end
; rel
++)
352 unsigned long r_symndx
;
353 struct elf_link_hash_entry
*h
;
355 r_symndx
= ELF32_R_SYM (rel
->r_info
);
356 if (r_symndx
< symtab_hdr
->sh_info
)
359 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
361 r_type
= (enum reloc_type
) ELF32_R_TYPE (rel
->r_info
);
367 case R_V850_16_PCREL
:
368 case R_V850_22_PCREL
:
377 case R_V850_SDA_OFFSET
:
378 other
= V850_OTHER_SDA
;
380 goto small_data_common
;
382 case R_V850_ZDA_OFFSET
:
383 other
= V850_OTHER_ZDA
;
385 goto small_data_common
;
387 case R_V850_TDA_OFFSET
:
388 other
= V850_OTHER_TDA
;
392 #define V850_OTHER_MASK (V850_OTHER_TDA | V850_OTHER_SDA | V850_OTHER_ZDA)
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)
403 switch (h
->other
& V850_OTHER_MASK
)
406 msg
= "Variable cannot occupy in multiple small data regions";
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";
411 case V850_OTHER_SDA
| V850_OTHER_ZDA
:
412 msg
= "Variable cannot be in both small and zero data regions simultaneously";
414 case V850_OTHER_SDA
| V850_OTHER_TDA
:
415 msg
= "Variable cannot be in both small and tiny data regions simultaneously";
417 case V850_OTHER_ZDA
| V850_OTHER_TDA
:
418 msg
= "Variable cannot be in both zero and tiny data regions simultaneously";
422 (*info
->callbacks
->warning
) (info
, msg
, h
->root
.root
.string
,
423 abfd
, h
->root
.u
.def
.section
, 0);
425 bfd_set_error (bfd_error_bad_value
);
426 h
->other
|= V850_OTHER_ERROR
;
431 if (h
&& h
->root
.type
== bfd_link_hash_common
433 && !strcmp (bfd_get_section_name (abfd
, h
->root
.u
.c
.p
->section
), "COMMON"))
435 asection
*section
= h
->root
.u
.c
.p
->section
= bfd_make_section_old_way (abfd
, common
);
436 section
->flags
|= SEC_IS_COMMON
;
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" : "");
453 static bfd_reloc_status_type
454 v850_elf_reloc (abfd
, reloc
, symbol
, data
, isection
, obfd
, err
)
463 if (obfd
!= (bfd
*) NULL
464 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
465 && (! reloc
->howto
->partial_inplace
466 || reloc
->addend
== 0))
468 reloc
->address
+= isection
->output_offset
;
471 else if (obfd
!= NULL
)
473 return bfd_reloc_continue
;
476 /* Catch relocs involving undefined symbols. */
477 if (bfd_is_und_section (symbol
->section
)
478 && (symbol
->flags
& BSF_WEAK
) == 0
480 return bfd_reloc_undefined
;
482 /* We handle final linking of some relocs ourselves. */
484 long relocation
, insn
;
486 /* Is the address of the relocation really within the section? */
487 if (reloc
->address
> isection
->_cooked_size
)
488 return bfd_reloc_outofrange
;
490 /* Work out which section the relocation is targetted at and the
491 initial relocation command value. */
493 /* Get symbol value. (Common symbols are special.) */
494 if (bfd_is_com_section (symbol
->section
))
497 relocation
= symbol
->value
;
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
;
504 if (reloc
->howto
->pc_relative
== true)
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
;
510 /* Deal with pcrel_offset */
511 relocation
-= reloc
->address
;
514 /* I've got no clue... */
517 switch (reloc
->howto
->type
)
520 return bfd_reloc_notsupported
;
522 case R_V850_22_PCREL
:
523 if (relocation
> 0x1ffff || relocation
< -0x200000)
524 return bfd_reloc_overflow
;
526 if ((relocation
% 2) != 0)
527 return bfd_reloc_dangerous
;
529 insn
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ reloc
->address
);
531 insn
|= (((relocation
& 0xfffe) << 16)
532 | ((relocation
& 0x3f0000) >> 16));
533 bfd_put_32 (abfd
, insn
, (bfd_byte
*)data
+ reloc
->address
);
536 case R_V850_16_PCREL
:
537 if (relocation
> 0x7fff || relocation
< -0x10000)
538 return bfd_reloc_overflow
;
540 if ((relocation
% 2) != 0)
541 return bfd_reloc_dangerous
;
543 insn
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ reloc
->address
);
545 insn
|= ((relocation
& 0xfffe) << 16);
546 bfd_put_32 (abfd
, insn
, (bfd_byte
*) data
+ reloc
->address
);
550 if (relocation
> 0xff || relocation
< -0x100)
551 return bfd_reloc_overflow
;
553 if ((relocation
% 2) != 0)
554 return bfd_reloc_dangerous
;
556 insn
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ reloc
->address
);
558 insn
|= ((relocation
& 0x1f0) << 7) | ((relocation
& 0x0e) << 3);
559 bfd_put_16 (abfd
, insn
, (bfd_byte
*)data
+ reloc
->address
);
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
);
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
);
575 case R_V850_ZDA_OFFSET
:
576 relocation
+= (short)bfd_get_16 (abfd
, (bfd_byte
*) data
+ reloc
->address
);
578 if ((long)relocation
> 0x7fff || (long)relocation
< -0x8000)
579 return bfd_reloc_overflow
;
581 bfd_put_16 (abfd
, relocation
, (bfd_byte
*)data
+ reloc
->address
);
585 case R_V850_SDA_OFFSET
:
588 struct bfd_link_hash_entry
*h
;
590 relocation
+= (short)bfd_get_16 (abfd
, (bfd_byte
*) data
+ reloc
->address
);
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
;
599 + h
->u
.def
.section
->output_section
->vma
600 + h
->u
.def
.section
->output_offset
);
603 if ((long)relocation
> 0x7fff || (long)relocation
< -0x8000)
604 return bfd_reloc_overflow
;
606 bfd_put_16 (abfd
, relocation
, (bfd_byte
*)data
+ reloc
->address
);
613 return bfd_reloc_continue
;
619 v850_elf_is_local_label_name (abfd
, name
)
623 return ((name
[0] == '.' && (name
[1] == 'L' || name
[1] == '.'))
624 || (name
[0] == '_' && name
[1] == '.' && name
[2] == 'L'
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
;
637 asection
*input_section
;
642 struct bfd_link_info
*info
;
647 unsigned long r_type
= howto
->type
;
648 bfd_byte
*hit_data
= contents
+ offset
;
653 value
-= (input_section
->output_section
->vma
654 + input_section
->output_offset
);
657 if ((long)value
> 0xff || (long)value
< -0x100)
658 return bfd_reloc_overflow
;
660 if ((value
% 2) != 0)
661 return bfd_reloc_dangerous
;
663 insn
= bfd_get_16 (input_bfd
, hit_data
);
665 insn
|= ((value
& 0x1f0) << 7) | ((value
& 0x0e) << 3);
666 bfd_put_16 (input_bfd
, insn
, hit_data
);
669 case R_V850_16_PCREL
:
670 value
-= (input_section
->output_section
->vma
+ input_section
->output_offset
);
673 if ((long)value
> 0x7fff || (long)value
< -0x10000)
674 return bfd_reloc_overflow
;
676 if ((value
% 2) != 0)
677 return bfd_reloc_dangerous
;
679 insn
= bfd_get_32 (input_bfd
, hit_data
);
681 insn
|= ((value
& 0xfffe) << 16);
682 bfd_put_32 (input_bfd
, insn
, hit_data
);
685 case R_V850_22_PCREL
:
686 value
-= (input_section
->output_section
->vma
687 + input_section
->output_offset
);
690 if ((long)value
> 0x1ffff || (long)value
< -0x200000)
691 return bfd_reloc_overflow
;
693 if ((value
% 2) != 0)
694 return bfd_reloc_dangerous
;
696 insn
= bfd_get_32 (input_bfd
, hit_data
);
698 insn
|= (((value
& 0xfffe) << 16) | ((value
& 0x3f0000) >> 16));
699 bfd_put_32 (input_bfd
, insn
, hit_data
);
703 value
+= (short)bfd_get_16 (input_bfd
, hit_data
);
704 value
= (value
>> 16) + ((value
& 0x8000) != 0);
706 if ((long)value
> 0x7fff || (long)value
< -0x8000)
707 return bfd_reloc_overflow
;
709 bfd_put_16 (input_bfd
, value
, hit_data
);
713 value
+= (short)bfd_get_16 (input_bfd
, hit_data
);
716 if ((long)value
> 0x7fff || (long)value
< -0x8000)
717 return bfd_reloc_overflow
;
719 bfd_put_16 (input_bfd
, value
, hit_data
);
723 value
+= (short)bfd_get_16 (input_bfd
, hit_data
);
726 bfd_put_16 (input_bfd
, value
, hit_data
);
730 case R_V850_ZDA_OFFSET
:
731 value
+= (short)bfd_get_16 (input_bfd
, hit_data
);
733 if ((long)value
> 0x7fff || (long)value
< -0x8000)
734 return bfd_reloc_overflow
;
736 bfd_put_16 (input_bfd
, value
, hit_data
);
740 value
+= bfd_get_32 (input_bfd
, hit_data
);
741 bfd_put_32 (input_bfd
, value
, hit_data
);
745 value
+= (char)bfd_get_8 (input_bfd
, hit_data
);
747 if ((long)value
> 0x7f || (long)value
< -0x80)
748 return bfd_reloc_overflow
;
750 bfd_put_8 (input_bfd
, value
, hit_data
);
753 case R_V850_SDA_OFFSET
:
756 struct bfd_link_hash_entry
*h
;
758 value
+= (short)bfd_get_16 (input_bfd
, hit_data
);
760 /* Get the value of __gp. */
761 h
= bfd_link_hash_lookup (info
->hash
, "__gp", false,
763 if (h
== (struct bfd_link_hash_entry
*) NULL
764 || h
->type
!= bfd_link_hash_defined
)
765 return bfd_reloc_undefined
;
768 + h
->u
.def
.section
->output_section
->vma
769 + h
->u
.def
.section
->output_offset
);
772 if ((long)value
> 0x7fff || (long)value
< -0x8000)
773 return bfd_reloc_overflow
;
775 bfd_put_16 (input_bfd
, value
, hit_data
);
779 case R_V850_TDA_OFFSET
:
782 struct bfd_link_hash_entry
*h
;
784 insn
= bfd_get_16 (input_bfd
, hit_data
);
786 /* Get the value of __ep. */
787 h
= bfd_link_hash_lookup (info
->hash
, "__ep", false,
789 if (h
== (struct bfd_link_hash_entry
*) NULL
790 || h
->type
!= bfd_link_hash_defined
)
791 return bfd_reloc_undefined
;
794 + h
->u
.def
.section
->output_section
->vma
795 + h
->u
.def
.section
->output_offset
);
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)
804 value
+= ((insn
& 0x7f) << 1);
806 /* Handle sld.w and sst.w -- 8 bit unsigned offset */
807 if ((long) value
> 0xff || (long) value
< 0)
808 return bfd_reloc_overflow
;
810 if ((value
% 2) != 0)
811 return bfd_reloc_dangerous
;
814 insn
|= (value
>> 1);
815 bfd_put_16 (input_bfd
, insn
, hit_data
);
819 if ((insn
& 0x0780) == 0x0400 || (insn
& 0x0780) == 0x0480)
821 value
+= ((insn
& 0x7f) << 1);
823 /* Handle sld.h and sst.h -- 8 bit unsigned offset */
824 if ((long) value
> 0xff || (long) value
< 0)
825 return bfd_reloc_overflow
;
827 if ((value
% 2) != 0)
828 return bfd_reloc_dangerous
;
831 insn
|= (value
>> 1);
832 bfd_put_16 (input_bfd
, insn
, hit_data
);
836 if ((insn
& 0x0780) == 0x0300 || (insn
& 0x0780) == 0x0380)
838 value
+= (insn
& 0x7f);
840 /* Handle sld.b and sst.b -- 7 bit unsigned offset */
841 if ((long) value
> 0x7f || (long) value
< 0)
842 return bfd_reloc_overflow
;
845 bfd_put_16 (input_bfd
, insn
, hit_data
);
849 /* Guess (XXX) that it's a movea instruction or something
851 value
+= (short)insn
;
852 if ((long)value
> 0x7fff || (long)value
< -0x8000)
853 return bfd_reloc_overflow
;
855 bfd_put_16 (input_bfd
, value
, hit_data
);
863 return bfd_reloc_notsupported
;
868 /* Relocate an V850 ELF section. */
870 v850_elf_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
871 contents
, relocs
, local_syms
, local_sections
)
873 struct bfd_link_info
*info
;
875 asection
*input_section
;
877 Elf_Internal_Rela
*relocs
;
878 Elf_Internal_Sym
*local_syms
;
879 asection
**local_sections
;
881 Elf_Internal_Shdr
*symtab_hdr
;
882 struct elf_link_hash_entry
**sym_hashes
;
883 Elf_Internal_Rela
*rel
, *relend
;
885 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
886 sym_hashes
= elf_sym_hashes (input_bfd
);
889 relend
= relocs
+ input_section
->reloc_count
;
890 for (; rel
< relend
; rel
++)
893 reloc_howto_type
*howto
;
894 unsigned long r_symndx
;
895 Elf_Internal_Sym
*sym
;
897 struct elf_link_hash_entry
*h
;
899 bfd_reloc_status_type r
;
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
;
905 if (info
->relocateable
)
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
)
913 sym
= local_syms
+ r_symndx
;
914 if (ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
916 sec
= local_sections
[r_symndx
];
917 rel
->r_addend
+= sec
->output_offset
+ sym
->st_value
;
924 /* This is a final link. */
928 if (r_symndx
< symtab_hdr
->sh_info
)
930 sym
= local_syms
+ r_symndx
;
931 sec
= local_sections
[r_symndx
];
932 relocation
= (sec
->output_section
->vma
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
)
945 sec
= h
->root
.u
.def
.section
;
946 relocation
= (h
->root
.u
.def
.value
947 + sec
->output_section
->vma
948 + sec
->output_offset
);
950 else if (h
->root
.type
== bfd_link_hash_undefweak
)
954 if (! ((*info
->callbacks
->undefined_symbol
)
955 (info
, h
->root
.root
.string
, input_bfd
,
956 input_section
, rel
->r_offset
)))
962 /* FIXME: We should use the addend, but the COFF relocations
964 r
= v850_elf_final_link_relocate (howto
, input_bfd
, output_bfd
,
966 contents
, rel
->r_offset
,
967 relocation
, rel
->r_addend
,
968 info
, sec
, h
== NULL
);
970 if (r
!= bfd_reloc_ok
)
973 const char *msg
= (const char *)0;
976 name
= h
->root
.root
.string
;
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
);
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
)))
994 case bfd_reloc_undefined
:
995 if (! ((*info
->callbacks
->undefined_symbol
)
996 (info
, name
, input_bfd
, input_section
,
1001 case bfd_reloc_outofrange
:
1002 msg
= "internal error: out of range error";
1005 case bfd_reloc_notsupported
:
1006 msg
= "internal error: unsupported relocation error";
1009 case bfd_reloc_dangerous
:
1010 msg
= "internal error: dangerous error";
1014 msg
= "internal error: unknown error";
1018 if (!((*info
->callbacks
->warning
)
1019 (info
, msg
, name
, input_bfd
, input_section
,
1030 /* Set the right machine number. */
1033 v850_elf_object_p (abfd
)
1036 switch (get_elf_backend_data (abfd
) -> elf_machine_code
)
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 */
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 */
1063 #define ELF_MAXPAGESIZE 0x1000
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
1073 #define elf_symbol_leading_char '_'
1075 #include "elf32-target.h"