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
PARAMS ((bfd
*, asymbol
*));
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 22 bit branch. */
86 HOWTO (R_V850_22_PCREL
, /* type */
88 2, /* size (0 = byte, 1 = short, 2 = long) */
90 true, /* pc_relative */
92 complain_overflow_signed
, /* complain_on_overflow */
93 v850_elf_reloc
, /* special_function */
94 "R_V850_22_PCREL", /* name */
95 false, /* partial_inplace */
96 0x07ffff80, /* src_mask */
97 0x07ffff80, /* dst_mask */
98 true), /* pcrel_offset */
100 /* High 16 bits of symbol value. */
101 HOWTO (R_V850_HI16_S
, /* type */
103 1, /* size (0 = byte, 1 = short, 2 = long) */
105 false, /* pc_relative */
107 complain_overflow_dont
, /* complain_on_overflow */
108 v850_elf_reloc
, /* special_function */
109 "R_V850_HI16_S", /* name */
110 true, /* partial_inplace */
111 0xffff, /* src_mask */
112 0xffff, /* dst_mask */
113 false), /* pcrel_offset */
115 /* High 16 bits of symbol value. */
116 HOWTO (R_V850_HI16
, /* 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", /* name */
125 true, /* partial_inplace */
126 0xffff, /* src_mask */
127 0xffff, /* dst_mask */
128 false), /* pcrel_offset */
130 /* Low 16 bits of symbol value. */
131 HOWTO (R_V850_LO16
, /* type */
133 1, /* size (0 = byte, 1 = short, 2 = long) */
135 false, /* pc_relative */
137 complain_overflow_dont
, /* complain_on_overflow */
138 bfd_elf_generic_reloc
, /* special_function */
139 "R_V850_LO16", /* name */
140 true, /* partial_inplace */
141 0xffff, /* src_mask */
142 0xffff, /* dst_mask */
143 false), /* pcrel_offset */
145 /* Simple 32bit reloc. */
146 HOWTO (R_V850_32
, /* type */
148 2, /* size (0 = byte, 1 = short, 2 = long) */
150 false, /* pc_relative */
152 complain_overflow_dont
, /* complain_on_overflow */
153 bfd_elf_generic_reloc
, /* special_function */
154 "R_V850_32", /* name */
155 true, /* partial_inplace */
156 0xffffffff, /* src_mask */
157 0xffffffff, /* dst_mask */
158 false), /* pcrel_offset */
160 /* Simple 16bit reloc. */
161 HOWTO (R_V850_16
, /* type */
163 1, /* 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_16", /* name */
170 true, /* partial_inplace */
171 0xffff, /* src_mask */
172 0xffff, /* dst_mask */
173 false), /* pcrel_offset */
175 /* Simple 8bit reloc. */
176 HOWTO (R_V850_8
, /* type */
178 0, /* 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_8", /* name */
185 true, /* partial_inplace */
188 false), /* pcrel_offset */
190 /* Offset from the short data area pointer. */
191 HOWTO (R_V850_SDA_OFFSET
, /* type */
193 1, /* 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_SDA_OFFSET", /* name */
200 true, /* partial_inplace */
201 0xffff, /* src_mask */
202 0xffff, /* dst_mask */
203 false), /* pcrel_offset */
205 /* Offset from the zero data area pointer. */
206 HOWTO (R_V850_ZDA_OFFSET
, /* type */
208 1, /* size (0 = byte, 1 = short, 2 = long) */
210 false, /* pc_relative */
212 complain_overflow_dont
, /* complain_on_overflow */
213 bfd_elf_generic_reloc
, /* special_function */
214 "R_V850_ZDA_OFFSET", /* name */
215 true, /* partial_inplace */
216 0xffff, /* src_mask */
217 0xffff, /* dst_mask */
218 false), /* pcrel_offset */
220 /* Offset from the tiny data area pointer. */
221 HOWTO (R_V850_TDA_OFFSET
, /* type */
223 2, /* size (0 = byte, 1 = short, 2 = long) */
225 false, /* pc_relative */
227 complain_overflow_dont
, /* complain_on_overflow */
228 bfd_elf_generic_reloc
, /* special_function */
229 "R_V850_TDA_OFFSET", /* name */
230 true, /* partial_inplace */
233 false), /* pcrel_offset */
237 /* Map BFD reloc types to V850 ELF reloc types. */
239 struct v850_elf_reloc_map
241 unsigned char bfd_reloc_val
;
242 unsigned char elf_reloc_val
;
245 static const struct v850_elf_reloc_map v850_elf_reloc_map
[] =
247 { BFD_RELOC_NONE
, R_V850_NONE
, },
248 { BFD_RELOC_V850_9_PCREL
, R_V850_9_PCREL
, },
249 { BFD_RELOC_V850_22_PCREL
, R_V850_22_PCREL
, },
250 { BFD_RELOC_HI16_S
, R_V850_HI16_S
, },
251 { BFD_RELOC_HI16
, R_V850_HI16
, },
252 { BFD_RELOC_LO16
, R_V850_LO16
, },
253 { BFD_RELOC_32
, R_V850_32
, },
254 { BFD_RELOC_16
, R_V850_16
, },
255 { BFD_RELOC_8
, R_V850_8
, },
256 { BFD_RELOC_V850_TDA_OFFSET
, R_V850_TDA_OFFSET
, },
257 { BFD_RELOC_V850_SDA_OFFSET
, R_V850_SDA_OFFSET
, },
258 { BFD_RELOC_V850_ZDA_OFFSET
, R_V850_ZDA_OFFSET
, },
262 /* Map a bfd relocation into the appropriate howto structure */
263 static reloc_howto_type
*
264 v850_elf_reloc_type_lookup (abfd
, code
)
266 bfd_reloc_code_real_type code
;
271 i
< sizeof (v850_elf_reloc_map
) / sizeof (struct v850_elf_reloc_map
);
274 if (v850_elf_reloc_map
[i
].bfd_reloc_val
== code
)
275 return &v850_elf_howto_table
[v850_elf_reloc_map
[i
].elf_reloc_val
];
282 /* Set the howto pointer for an V850 ELF reloc. */
284 v850_elf_info_to_howto_rel (abfd
, cache_ptr
, dst
)
287 Elf32_Internal_Rel
*dst
;
291 r_type
= ELF32_R_TYPE (dst
->r_info
);
292 BFD_ASSERT (r_type
< (unsigned int) R_V850_max
);
293 cache_ptr
->howto
= &v850_elf_howto_table
[r_type
];
297 /* Look through the relocs for a section during the first phase, and
298 allocate space in the global offset table or procedure linkage
302 v850_elf_check_relocs (abfd
, info
, sec
, relocs
)
304 struct bfd_link_info
*info
;
306 const Elf_Internal_Rela
*relocs
;
310 Elf_Internal_Shdr
*symtab_hdr
;
311 struct elf_link_hash_entry
**sym_hashes
;
312 const Elf_Internal_Rela
*rel
;
313 const Elf_Internal_Rela
*rel_end
;
315 enum reloc_type r_type
;
317 const char *common
= (const char *)0;
319 if (info
->relocateable
)
323 fprintf (stderr
, "v850_elf_check_relocs called for section %s in %s\n",
324 bfd_get_section_name (abfd
, sec
),
325 bfd_get_filename (abfd
));
328 dynobj
= elf_hash_table (info
)->dynobj
;
329 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
330 sym_hashes
= elf_sym_hashes (abfd
);
333 rel_end
= relocs
+ sec
->reloc_count
;
334 for (rel
= relocs
; rel
< rel_end
; rel
++)
336 unsigned long r_symndx
;
337 struct elf_link_hash_entry
*h
;
339 r_symndx
= ELF32_R_SYM (rel
->r_info
);
340 if (r_symndx
< symtab_hdr
->sh_info
)
343 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
345 r_type
= (enum reloc_type
) ELF32_R_TYPE (rel
->r_info
);
351 case R_V850_22_PCREL
:
360 case R_V850_SDA_OFFSET
:
361 other
= V850_OTHER_SDA
;
363 goto small_data_common
;
365 case R_V850_ZDA_OFFSET
:
366 other
= V850_OTHER_ZDA
;
368 goto small_data_common
;
370 case R_V850_TDA_OFFSET
:
371 other
= V850_OTHER_TDA
;
375 #define V850_OTHER_MASK (V850_OTHER_TDA | V850_OTHER_SDA | V850_OTHER_ZDA)
380 h
->other
|= other
; /* flag which type of relocation was used */
381 if ((h
->other
& V850_OTHER_MASK
) != (other
& V850_OTHER_MASK
)
382 && (h
->other
& V850_OTHER_ERROR
) == 0)
386 switch (h
->other
& V850_OTHER_MASK
)
389 msg
= "Variable cannot occupy in multiple small data regions";
391 case V850_OTHER_SDA
| V850_OTHER_ZDA
| V850_OTHER_TDA
:
392 msg
= "Variable can only be in one of the small, zero, and tiny data regions";
394 case V850_OTHER_SDA
| V850_OTHER_ZDA
:
395 msg
= "Variable cannot be in both small and zero data regions simultaneously";
397 case V850_OTHER_SDA
| V850_OTHER_TDA
:
398 msg
= "Variable cannot be in both small and tiny data regions simultaneously";
400 case V850_OTHER_ZDA
| V850_OTHER_TDA
:
401 msg
= "Variable cannot be in both zero and tiny data regions simultaneously";
405 (*info
->callbacks
->warning
) (info
, msg
, h
->root
.root
.string
,
406 abfd
, h
->root
.u
.def
.section
, 0);
408 bfd_set_error (bfd_error_bad_value
);
409 h
->other
|= V850_OTHER_ERROR
;
414 if (h
->root
.type
== bfd_link_hash_common
416 && !strcmp (bfd_get_section_name (abfd
, h
->root
.u
.c
.p
->section
), "COMMON"))
418 asection
*section
= h
->root
.u
.c
.p
->section
= bfd_make_section_old_way (abfd
, common
);
419 section
->flags
|= SEC_IS_COMMON
;
423 fprintf (stderr
, "v850_elf_check_relocs, found %s relocation for %s%s\n",
424 v850_elf_howto_table
[ (int)r_type
].name
,
425 (h
&& h
->root
.root
.string
) ? h
->root
.root
.string
: "<unknown>",
426 (h
->root
.type
== bfd_link_hash_common
) ? ", symbol is common" : "");
436 static bfd_reloc_status_type
437 v850_elf_reloc (abfd
, reloc
, symbol
, data
, isection
, obfd
, err
)
446 if (obfd
!= (bfd
*) NULL
447 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
448 && (! reloc
->howto
->partial_inplace
449 || reloc
->addend
== 0))
451 reloc
->address
+= isection
->output_offset
;
454 else if (obfd
!= NULL
)
456 return bfd_reloc_continue
;
459 /* Catch relocs involving undefined symbols. */
460 if (bfd_is_und_section (symbol
->section
)
461 && (symbol
->flags
& BSF_WEAK
) == 0
463 return bfd_reloc_undefined
;
465 /* We handle final linking of some relocs ourselves. */
467 long relocation
, insn
;
469 /* Is the address of the relocation really within the section? */
470 if (reloc
->address
> isection
->_cooked_size
)
471 return bfd_reloc_outofrange
;
473 /* Work out which section the relocation is targetted at and the
474 initial relocation command value. */
476 /* Get symbol value. (Common symbols are special.) */
477 if (bfd_is_com_section (symbol
->section
))
480 relocation
= symbol
->value
;
482 /* Convert input-section-relative symbol value to absolute + addend. */
483 relocation
+= symbol
->section
->output_section
->vma
;
484 relocation
+= symbol
->section
->output_offset
;
485 relocation
+= reloc
->addend
;
487 if (reloc
->howto
->pc_relative
== true)
489 /* Here the variable relocation holds the final address of the
490 symbol we are relocating against, plus any addend. */
491 relocation
-= isection
->output_section
->vma
+ isection
->output_offset
;
493 /* Deal with pcrel_offset */
494 relocation
-= reloc
->address
;
497 /* I've got no clue... */
500 if (reloc
->howto
->type
== R_V850_22_PCREL
)
502 if (relocation
> 0x1ffff || relocation
< -0x200000)
503 return bfd_reloc_overflow
;
505 if ((relocation
% 2) != 0)
506 return bfd_reloc_dangerous
;
508 insn
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ reloc
->address
);
510 insn
|= (((relocation
& 0xfffe) << 16)
511 | ((relocation
& 0x3f0000) >> 16));
512 bfd_put_32 (abfd
, insn
, (bfd_byte
*)data
+ reloc
->address
);
515 else if (reloc
->howto
->type
== R_V850_9_PCREL
)
517 if (relocation
> 0xff || relocation
< -0x100)
518 return bfd_reloc_overflow
;
520 if ((relocation
% 2) != 0)
521 return bfd_reloc_dangerous
;
523 insn
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ reloc
->address
);
525 insn
|= ((relocation
& 0x1f0) << 7) | ((relocation
& 0x0e) << 3);
526 bfd_put_16 (abfd
, insn
, (bfd_byte
*)data
+ reloc
->address
);
529 else if (reloc
->howto
->type
== R_V850_HI16_S
)
531 relocation
+= bfd_get_16 (abfd
, (bfd_byte
*) data
+ reloc
->address
);
532 relocation
= (relocation
>> 16) + ((relocation
& 0x8000) != 0);
533 bfd_put_16 (abfd
, relocation
, (bfd_byte
*)data
+ reloc
->address
);
536 else if (reloc
->howto
->type
== R_V850_HI16
)
538 relocation
+= bfd_get_16 (abfd
, (bfd_byte
*) data
+ reloc
->address
);
539 relocation
= (relocation
>> 16);
540 bfd_put_16 (abfd
, relocation
, (bfd_byte
*)data
+ reloc
->address
);
544 return bfd_reloc_notsupported
;
547 return bfd_reloc_continue
;
553 v850_elf_is_local_label (abfd
, symbol
)
557 return ((symbol
->name
[0] == '.' && (symbol
->name
[1] == 'L' || symbol
->name
[1] == '.'))
558 || (symbol
->name
[0] == '_' && symbol
->name
[1] == '.' && symbol
->name
[2] == 'L'
559 && symbol
->name
[3] == '_'));
563 /* Perform a relocation as part of a final link. */
564 static bfd_reloc_status_type
565 v850_elf_final_link_relocate (howto
, input_bfd
, output_bfd
,
566 input_section
, contents
, offset
, value
,
567 addend
, info
, sym_sec
, is_local
)
568 reloc_howto_type
*howto
;
571 asection
*input_section
;
576 struct bfd_link_info
*info
;
581 unsigned long r_type
= howto
->type
;
582 unsigned long r_format
= howto
->bitsize
;
583 bfd_byte
*hit_data
= contents
+ offset
;
584 boolean r_pcrel
= howto
->pc_relative
;
589 value
-= (input_section
->output_section
->vma
590 + input_section
->output_offset
);
593 if ((long)value
> 0xff || (long)value
< -0x100)
594 return bfd_reloc_overflow
;
596 if ((value
% 2) != 0)
597 return bfd_reloc_dangerous
;
599 insn
= bfd_get_16 (input_bfd
, hit_data
);
601 insn
|= ((value
& 0x1f0) << 7) | ((value
& 0x0e) << 3);
602 bfd_put_16 (input_bfd
, insn
, hit_data
);
605 case R_V850_22_PCREL
:
606 value
-= (input_section
->output_section
->vma
607 + input_section
->output_offset
);
610 if ((long)value
> 0x1ffff || (long)value
< -0x200000)
611 return bfd_reloc_overflow
;
613 if ((value
% 2) != 0)
614 return bfd_reloc_dangerous
;
616 insn
= bfd_get_32 (input_bfd
, hit_data
);
618 insn
|= (((value
& 0xfffe) << 16) | ((value
& 0x3f0000) >> 16));
619 bfd_put_32 (input_bfd
, insn
, hit_data
);
623 value
+= (short)bfd_get_16 (input_bfd
, hit_data
);
624 value
= (value
>> 16) + ((value
& 0x8000) != 0);
626 if ((long)value
> 0x7fff || (long)value
< -0x8000)
627 return bfd_reloc_overflow
;
629 bfd_put_16 (input_bfd
, value
, hit_data
);
633 value
+= (short)bfd_get_16 (input_bfd
, hit_data
);
636 if ((long)value
> 0x7fff || (long)value
< -0x8000)
637 return bfd_reloc_overflow
;
639 bfd_put_16 (input_bfd
, value
, hit_data
);
643 value
+= (short)bfd_get_16 (input_bfd
, hit_data
);
646 bfd_put_16 (input_bfd
, value
, hit_data
);
650 case R_V850_ZDA_OFFSET
:
651 value
+= (short)bfd_get_16 (input_bfd
, hit_data
);
653 if ((long)value
> 0x7fff || (long)value
< -0x8000)
654 return bfd_reloc_overflow
;
656 bfd_put_16 (input_bfd
, value
, hit_data
);
660 value
+= bfd_get_32 (input_bfd
, hit_data
);
661 bfd_put_32 (input_bfd
, value
, hit_data
);
665 value
+= (char)bfd_get_8 (input_bfd
, hit_data
);
667 if ((long)value
> 0x7f || (long)value
< -0x80)
668 return bfd_reloc_overflow
;
670 bfd_put_8 (input_bfd
, value
, hit_data
);
673 case R_V850_SDA_OFFSET
:
676 struct bfd_link_hash_entry
*h
;
678 value
+= (short)bfd_get_16 (input_bfd
, hit_data
);
680 /* Get the value of __gp. */
681 h
= bfd_link_hash_lookup (info
->hash
, "__gp", false,
683 if (h
== (struct bfd_link_hash_entry
*) NULL
684 || h
->type
!= bfd_link_hash_defined
)
685 return bfd_reloc_undefined
;
688 + h
->u
.def
.section
->output_section
->vma
689 + h
->u
.def
.section
->output_offset
);
692 if ((long)value
> 0x7fff || (long)value
< -0x8000)
693 return bfd_reloc_overflow
;
695 bfd_put_16 (input_bfd
, value
, hit_data
);
699 case R_V850_TDA_OFFSET
:
702 struct bfd_link_hash_entry
*h
;
704 insn
= bfd_get_16 (input_bfd
, hit_data
);
706 /* Get the value of __ep. */
707 h
= bfd_link_hash_lookup (info
->hash
, "__ep", false,
709 if (h
== (struct bfd_link_hash_entry
*) NULL
710 || h
->type
!= bfd_link_hash_defined
)
711 return bfd_reloc_undefined
;
714 + h
->u
.def
.section
->output_section
->vma
715 + h
->u
.def
.section
->output_offset
);
719 /* Overflow computation and operand insertion is complicated
720 by valid offsets and insertions changing depending on the
721 instruction being used! */
722 if ((insn
& 0x0780) == 0x0500)
724 value
+= ((insn
& 0x7f) << 1);
726 /* Handle sld.w and sst.w -- 8 bit unsigned offset */
727 if ((long) value
> 0xff || (long) value
< 0)
728 return bfd_reloc_overflow
;
730 if ((value
% 2) != 0)
731 return bfd_reloc_dangerous
;
734 insn
|= (value
>> 1);
735 bfd_put_16 (input_bfd
, insn
, hit_data
);
739 if ((insn
& 0x0780) == 0x0400 || (insn
& 0x0780) == 0x0480)
741 value
+= ((insn
& 0x7f) << 1);
743 /* Handle sld.h and sst.h -- 8 bit unsigned offset */
744 if ((long) value
> 0xff || (long) value
< 0)
745 return bfd_reloc_overflow
;
747 if ((value
% 2) != 0)
748 return bfd_reloc_dangerous
;
751 insn
|= (value
>> 1);
752 bfd_put_16 (input_bfd
, insn
, hit_data
);
756 if ((insn
& 0x0780) == 0x0300 || (insn
& 0x0780) == 0x0380)
758 value
+= (insn
& 0x7f);
760 /* Handle sld.b and sst.b -- 7 bit unsigned offset */
761 if ((long) value
> 0x7f || (long) value
< 0)
762 return bfd_reloc_overflow
;
765 bfd_put_16 (input_bfd
, insn
, hit_data
);
769 /* Guess (XXX) that it's a movea instruction or something
771 value
+= (short)insn
;
772 if ((long)value
> 0x7fff || (long)value
< -0x8000)
773 return bfd_reloc_overflow
;
775 bfd_put_16 (input_bfd
, value
, hit_data
);
787 /* Relocate an V850 ELF section. */
789 v850_elf_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
790 contents
, relocs
, local_syms
, local_sections
)
792 struct bfd_link_info
*info
;
794 asection
*input_section
;
796 Elf_Internal_Rela
*relocs
;
797 Elf_Internal_Sym
*local_syms
;
798 asection
**local_sections
;
800 Elf_Internal_Shdr
*symtab_hdr
;
801 struct elf_link_hash_entry
**sym_hashes
;
802 Elf_Internal_Rela
*rel
, *relend
;
804 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
805 sym_hashes
= elf_sym_hashes (input_bfd
);
808 relend
= relocs
+ input_section
->reloc_count
;
809 for (; rel
< relend
; rel
++)
812 reloc_howto_type
*howto
;
813 unsigned long r_symndx
;
814 Elf_Internal_Sym
*sym
;
816 struct elf_link_hash_entry
*h
;
818 bfd_reloc_status_type r
;
820 if (info
->relocateable
)
822 /* This is a relocateable link. We don't have to change
823 anything, unless the reloc is against a section symbol,
824 in which case we have to adjust according to where the
825 section symbol winds up in the output section. */
826 if (r_symndx
< symtab_hdr
->sh_info
)
828 sym
= local_syms
+ r_symndx
;
829 if (ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
831 sec
= local_sections
[r_symndx
];
832 rel
->r_addend
+= sec
->output_offset
+ sym
->st_value
;
839 r_type
= ELF32_R_TYPE (rel
->r_info
);
841 howto
= v850_elf_howto_table
+ r_type
;
843 r_symndx
= ELF32_R_SYM (rel
->r_info
);
845 /* This is a final link. */
849 if (r_symndx
< symtab_hdr
->sh_info
)
851 sym
= local_syms
+ r_symndx
;
852 sec
= local_sections
[r_symndx
];
853 relocation
= (sec
->output_section
->vma
859 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
860 while (h
->root
.type
== bfd_link_hash_indirect
861 || h
->root
.type
== bfd_link_hash_warning
)
862 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
863 if (h
->root
.type
== bfd_link_hash_defined
864 || h
->root
.type
== bfd_link_hash_defweak
)
866 sec
= h
->root
.u
.def
.section
;
867 relocation
= (h
->root
.u
.def
.value
868 + sec
->output_section
->vma
869 + sec
->output_offset
);
871 else if (h
->root
.type
== bfd_link_hash_undefweak
)
875 if (! ((*info
->callbacks
->undefined_symbol
)
876 (info
, h
->root
.root
.string
, input_bfd
,
877 input_section
, rel
->r_offset
)))
883 /* FIXME: We should use the addend, but the COFF relocations
885 r
= v850_elf_final_link_relocate (howto
, input_bfd
, output_bfd
,
887 contents
, rel
->r_offset
,
888 relocation
, rel
->r_addend
,
889 info
, sec
, h
== NULL
);
891 if (r
!= bfd_reloc_ok
)
896 case bfd_reloc_outofrange
:
898 case bfd_reloc_overflow
:
903 name
= h
->root
.root
.string
;
906 name
= (bfd_elf_string_from_elf_section
907 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
));
911 name
= bfd_section_name (input_bfd
, sec
);
913 if (! ((*info
->callbacks
->reloc_overflow
)
914 (info
, name
, howto
->name
, (bfd_vma
) 0,
915 input_bfd
, input_section
, rel
->r_offset
)))
927 #define TARGET_LITTLE_SYM bfd_elf32_v850_vec
928 #define TARGET_LITTLE_NAME "elf32-v850"
929 #define ELF_ARCH bfd_arch_v850
930 #define ELF_MACHINE_CODE EM_CYGNUS_V850
931 #define ELF_MAXPAGESIZE 0x1000
933 #define elf_info_to_howto 0
934 #define elf_info_to_howto_rel v850_elf_info_to_howto_rel
935 #define elf_backend_check_relocs v850_elf_check_relocs
936 #define elf_backend_relocate_section v850_elf_relocate_section
937 #define bfd_elf32_bfd_is_local_label v850_elf_is_local_label
938 #define bfd_elf32_bfd_reloc_type_lookup v850_elf_reloc_type_lookup
940 #define elf_symbol_leading_char '_'
942 #include "elf32-target.h"