1 |
/* V850-specific support for 32-bit ELF |
/* V850-specific support for 32-bit ELF |
2 |
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 |
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 |
3 |
Free Software Foundation, Inc. |
Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
6 |
|
|
7 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
8 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
9 |
the Free Software Foundation; either version 2 of the License, or |
the Free Software Foundation; either version 2 of the License, or |
10 |
(at your option) any later version. |
(at your option) any later version. |
11 |
|
|
12 |
This program is distributed in the hope that it will be useful, |
This program is distributed in the hope that it will be useful, |
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
GNU General Public License for more details. |
GNU General Public License for more details. |
16 |
|
|
17 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
18 |
along with this program; if not, write to the Free Software |
along with this program; if not, write to the Free Software |
19 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
20 |
|
|
21 |
/* XXX FIXME: This code is littered with 32bit int, 16bit short, 8bit char |
/* XXX FIXME: This code is littered with 32bit int, 16bit short, 8bit char |
22 |
dependencies. As is the gas & simulator code or the v850. */ |
dependencies. As is the gas & simulator code for the v850. */ |
23 |
|
|
24 |
#include "bfd.h" |
#include "bfd.h" |
25 |
#include "sysdep.h" |
#include "sysdep.h" |
35 |
static reloc_howto_type *v850_elf_reloc_type_lookup |
static reloc_howto_type *v850_elf_reloc_type_lookup |
36 |
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); |
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); |
37 |
static void v850_elf_info_to_howto_rel |
static void v850_elf_info_to_howto_rel |
38 |
PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *)); |
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); |
39 |
static void v850_elf_info_to_howto_rela |
static void v850_elf_info_to_howto_rela |
40 |
PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *)); |
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); |
41 |
static bfd_reloc_status_type v850_elf_reloc |
static bfd_reloc_status_type v850_elf_reloc |
42 |
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); |
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); |
43 |
static boolean v850_elf_is_local_label_name |
static bfd_boolean v850_elf_is_local_label_name |
44 |
PARAMS ((bfd *, const char *)); |
PARAMS ((bfd *, const char *)); |
45 |
static boolean v850_elf_relocate_section |
static bfd_boolean v850_elf_relocate_section |
46 |
PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
47 |
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); |
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); |
48 |
static bfd_reloc_status_type v850_elf_perform_relocation |
static bfd_reloc_status_type v850_elf_perform_relocation |
49 |
PARAMS ((bfd *, unsigned int, bfd_vma, bfd_byte *)); |
PARAMS ((bfd *, unsigned int, bfd_vma, bfd_byte *)); |
50 |
static boolean v850_elf_check_relocs |
static bfd_boolean v850_elf_check_relocs |
51 |
PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)); |
PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)); |
52 |
static void remember_hi16s_reloc |
static void remember_hi16s_reloc |
53 |
PARAMS ((bfd *, bfd_vma, bfd_byte *)); |
PARAMS ((bfd *, bfd_vma, bfd_byte *)); |
54 |
static bfd_byte * find_remembered_hi16s_reloc |
static bfd_byte * find_remembered_hi16s_reloc |
55 |
PARAMS ((bfd_vma, boolean *)); |
PARAMS ((bfd_vma, bfd_boolean *)); |
56 |
static bfd_reloc_status_type v850_elf_final_link_relocate |
static bfd_reloc_status_type v850_elf_final_link_relocate |
57 |
PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *, bfd_vma, |
PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *, bfd_vma, |
58 |
bfd_vma, bfd_vma, struct bfd_link_info *, asection *, int)); |
bfd_vma, bfd_vma, struct bfd_link_info *, asection *, int)); |
59 |
static boolean v850_elf_object_p |
static bfd_boolean v850_elf_object_p |
60 |
PARAMS ((bfd *)); |
PARAMS ((bfd *)); |
61 |
static boolean v850_elf_fake_sections |
static bfd_boolean v850_elf_fake_sections |
62 |
PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *)); |
PARAMS ((bfd *, Elf_Internal_Shdr *, asection *)); |
63 |
static void v850_elf_final_write_processing |
static void v850_elf_final_write_processing |
64 |
PARAMS ((bfd *, boolean)); |
PARAMS ((bfd *, bfd_boolean)); |
65 |
static boolean v850_elf_set_private_flags |
static bfd_boolean v850_elf_set_private_flags |
66 |
PARAMS ((bfd *, flagword)); |
PARAMS ((bfd *, flagword)); |
67 |
static boolean v850_elf_merge_private_bfd_data |
static bfd_boolean v850_elf_merge_private_bfd_data |
68 |
PARAMS ((bfd *, bfd *)); |
PARAMS ((bfd *, bfd *)); |
69 |
static boolean v850_elf_print_private_bfd_data |
static bfd_boolean v850_elf_print_private_bfd_data |
70 |
PARAMS ((bfd *, PTR)); |
PARAMS ((bfd *, PTR)); |
71 |
static boolean v850_elf_section_from_bfd_section |
static bfd_boolean v850_elf_section_from_bfd_section |
72 |
PARAMS ((bfd *, asection *, int *)); |
PARAMS ((bfd *, asection *, int *)); |
73 |
static void v850_elf_symbol_processing |
static void v850_elf_symbol_processing |
74 |
PARAMS ((bfd *, asymbol *)); |
PARAMS ((bfd *, asymbol *)); |
75 |
static boolean v850_elf_add_symbol_hook |
static bfd_boolean v850_elf_add_symbol_hook |
76 |
PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, |
PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Sym *, |
77 |
const char **, flagword *, asection **, bfd_vma *)); |
const char **, flagword *, asection **, bfd_vma *)); |
78 |
static boolean v850_elf_link_output_symbol_hook |
static bfd_boolean v850_elf_link_output_symbol_hook |
79 |
PARAMS ((bfd *, struct bfd_link_info *, const char *, |
PARAMS ((struct bfd_link_info *, const char *, Elf_Internal_Sym *, |
80 |
Elf_Internal_Sym *, asection *)); |
asection *, struct elf_link_hash_entry *)); |
81 |
static boolean v850_elf_section_from_shdr |
static bfd_boolean v850_elf_section_from_shdr |
82 |
PARAMS ((bfd *, Elf_Internal_Shdr *, const char *)); |
PARAMS ((bfd *, Elf_Internal_Shdr *, const char *)); |
83 |
static boolean v850_elf_gc_sweep_hook |
static bfd_boolean v850_elf_gc_sweep_hook |
84 |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
85 |
const Elf_Internal_Rela *)); |
const Elf_Internal_Rela *)); |
86 |
static asection * v850_elf_gc_mark_hook |
static asection * v850_elf_gc_mark_hook |
87 |
PARAMS ((asection *, struct bfd_link_info *, |
PARAMS ((asection *, struct bfd_link_info *, |
88 |
Elf_Internal_Rela *, struct elf_link_hash_entry *, |
Elf_Internal_Rela *, struct elf_link_hash_entry *, |
89 |
Elf_Internal_Sym *)); |
Elf_Internal_Sym *)); |
90 |
|
static bfd_reloc_status_type v850_elf_ignore_reloc |
91 |
|
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); |
92 |
|
static bfd_boolean v850_elf_relax_delete_bytes |
93 |
|
PARAMS ((bfd *, asection *, bfd_vma, bfd_vma, int)); |
94 |
|
static bfd_boolean v850_elf_relax_section |
95 |
|
PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *)); |
96 |
|
|
97 |
/* Note: It is REQUIRED that the 'type' value of each entry |
/* Note: It is REQUIRED that the 'type' value of each entry |
98 |
in this array match the index of the entry in the array. */ |
in this array match the index of the entry in the array. */ |
103 |
0, /* rightshift */ |
0, /* rightshift */ |
104 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
105 |
32, /* bitsize */ |
32, /* bitsize */ |
106 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
107 |
0, /* bitpos */ |
0, /* bitpos */ |
108 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
109 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
110 |
"R_V850_NONE", /* name */ |
"R_V850_NONE", /* name */ |
111 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
112 |
0, /* src_mask */ |
0, /* src_mask */ |
113 |
0, /* dst_mask */ |
0, /* dst_mask */ |
114 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
115 |
|
|
116 |
/* A PC relative 9 bit branch. */ |
/* A PC relative 9 bit branch. */ |
117 |
HOWTO (R_V850_9_PCREL, /* type */ |
HOWTO (R_V850_9_PCREL, /* type */ |
118 |
2, /* rightshift */ |
2, /* rightshift */ |
119 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
120 |
26, /* bitsize */ |
26, /* bitsize */ |
121 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
122 |
0, /* bitpos */ |
0, /* bitpos */ |
123 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
124 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
125 |
"R_V850_9_PCREL", /* name */ |
"R_V850_9_PCREL", /* name */ |
126 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
127 |
0x00ffffff, /* src_mask */ |
0x00ffffff, /* src_mask */ |
128 |
0x00ffffff, /* dst_mask */ |
0x00ffffff, /* dst_mask */ |
129 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
130 |
|
|
131 |
/* A PC relative 22 bit branch. */ |
/* A PC relative 22 bit branch. */ |
132 |
HOWTO (R_V850_22_PCREL, /* type */ |
HOWTO (R_V850_22_PCREL, /* type */ |
133 |
2, /* rightshift */ |
2, /* rightshift */ |
134 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
135 |
22, /* bitsize */ |
22, /* bitsize */ |
136 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
137 |
7, /* bitpos */ |
7, /* bitpos */ |
138 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
139 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
140 |
"R_V850_22_PCREL", /* name */ |
"R_V850_22_PCREL", /* name */ |
141 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
142 |
0x07ffff80, /* src_mask */ |
0x07ffff80, /* src_mask */ |
143 |
0x07ffff80, /* dst_mask */ |
0x07ffff80, /* dst_mask */ |
144 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
145 |
|
|
146 |
/* High 16 bits of symbol value. */ |
/* High 16 bits of symbol value. */ |
147 |
HOWTO (R_V850_HI16_S, /* type */ |
HOWTO (R_V850_HI16_S, /* type */ |
148 |
0, /* rightshift */ |
0, /* rightshift */ |
149 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
150 |
16, /* bitsize */ |
16, /* bitsize */ |
151 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
152 |
0, /* bitpos */ |
0, /* bitpos */ |
153 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
154 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
155 |
"R_V850_HI16_S", /* name */ |
"R_V850_HI16_S", /* name */ |
156 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
157 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
158 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
159 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
160 |
|
|
161 |
/* High 16 bits of symbol value. */ |
/* High 16 bits of symbol value. */ |
162 |
HOWTO (R_V850_HI16, /* type */ |
HOWTO (R_V850_HI16, /* type */ |
163 |
0, /* rightshift */ |
0, /* rightshift */ |
164 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
165 |
16, /* bitsize */ |
16, /* bitsize */ |
166 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
167 |
0, /* bitpos */ |
0, /* bitpos */ |
168 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
169 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
170 |
"R_V850_HI16", /* name */ |
"R_V850_HI16", /* name */ |
171 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
172 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
173 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
174 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
175 |
|
|
176 |
/* Low 16 bits of symbol value. */ |
/* Low 16 bits of symbol value. */ |
177 |
HOWTO (R_V850_LO16, /* type */ |
HOWTO (R_V850_LO16, /* type */ |
178 |
0, /* rightshift */ |
0, /* rightshift */ |
179 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
180 |
16, /* bitsize */ |
16, /* bitsize */ |
181 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
182 |
0, /* bitpos */ |
0, /* bitpos */ |
183 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
184 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
185 |
"R_V850_LO16", /* name */ |
"R_V850_LO16", /* name */ |
186 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
187 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
188 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
189 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
190 |
|
|
191 |
/* Simple 32bit reloc. */ |
/* Simple 32bit reloc. */ |
192 |
HOWTO (R_V850_32, /* type */ |
HOWTO (R_V850_ABS32, /* type */ |
193 |
0, /* rightshift */ |
0, /* rightshift */ |
194 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
195 |
32, /* bitsize */ |
32, /* bitsize */ |
196 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
197 |
0, /* bitpos */ |
0, /* bitpos */ |
198 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
199 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
200 |
"R_V850_32", /* name */ |
"R_V850_ABS32", /* name */ |
201 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
202 |
0xffffffff, /* src_mask */ |
0xffffffff, /* src_mask */ |
203 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
204 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
205 |
|
|
206 |
/* Simple 16bit reloc. */ |
/* Simple 16bit reloc. */ |
207 |
HOWTO (R_V850_16, /* type */ |
HOWTO (R_V850_16, /* type */ |
208 |
0, /* rightshift */ |
0, /* rightshift */ |
209 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
210 |
16, /* bitsize */ |
16, /* bitsize */ |
211 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
212 |
0, /* bitpos */ |
0, /* bitpos */ |
213 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
214 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
215 |
"R_V850_16", /* name */ |
"R_V850_16", /* name */ |
216 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
217 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
218 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
219 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
220 |
|
|
221 |
/* Simple 8bit reloc. */ |
/* Simple 8bit reloc. */ |
222 |
HOWTO (R_V850_8, /* type */ |
HOWTO (R_V850_8, /* type */ |
223 |
0, /* rightshift */ |
0, /* rightshift */ |
224 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
225 |
8, /* bitsize */ |
8, /* bitsize */ |
226 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
227 |
0, /* bitpos */ |
0, /* bitpos */ |
228 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
229 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
230 |
"R_V850_8", /* name */ |
"R_V850_8", /* name */ |
231 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
232 |
0xff, /* src_mask */ |
0xff, /* src_mask */ |
233 |
0xff, /* dst_mask */ |
0xff, /* dst_mask */ |
234 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
235 |
|
|
236 |
/* 16 bit offset from the short data area pointer. */ |
/* 16 bit offset from the short data area pointer. */ |
237 |
HOWTO (R_V850_SDA_16_16_OFFSET, /* type */ |
HOWTO (R_V850_SDA_16_16_OFFSET, /* type */ |
238 |
0, /* rightshift */ |
0, /* rightshift */ |
239 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
240 |
16, /* bitsize */ |
16, /* bitsize */ |
241 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
242 |
0, /* bitpos */ |
0, /* bitpos */ |
243 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
244 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
245 |
"R_V850_SDA_16_16_OFFSET", /* name */ |
"R_V850_SDA_16_16_OFFSET", /* name */ |
246 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
247 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
248 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
249 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
250 |
|
|
251 |
/* 15 bit offset from the short data area pointer. */ |
/* 15 bit offset from the short data area pointer. */ |
252 |
HOWTO (R_V850_SDA_15_16_OFFSET, /* type */ |
HOWTO (R_V850_SDA_15_16_OFFSET, /* type */ |
253 |
1, /* rightshift */ |
1, /* rightshift */ |
254 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
255 |
16, /* bitsize */ |
16, /* bitsize */ |
256 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
257 |
1, /* bitpos */ |
1, /* bitpos */ |
258 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
259 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
260 |
"R_V850_SDA_15_16_OFFSET", /* name */ |
"R_V850_SDA_15_16_OFFSET", /* name */ |
261 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
262 |
0xfffe, /* src_mask */ |
0xfffe, /* src_mask */ |
263 |
0xfffe, /* dst_mask */ |
0xfffe, /* dst_mask */ |
264 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
265 |
|
|
266 |
/* 16 bit offset from the zero data area pointer. */ |
/* 16 bit offset from the zero data area pointer. */ |
267 |
HOWTO (R_V850_ZDA_16_16_OFFSET, /* type */ |
HOWTO (R_V850_ZDA_16_16_OFFSET, /* type */ |
268 |
0, /* rightshift */ |
0, /* rightshift */ |
269 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
270 |
16, /* bitsize */ |
16, /* bitsize */ |
271 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
272 |
0, /* bitpos */ |
0, /* bitpos */ |
273 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
274 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
275 |
"R_V850_ZDA_16_16_OFFSET", /* name */ |
"R_V850_ZDA_16_16_OFFSET", /* name */ |
276 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
277 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
278 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
279 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
280 |
|
|
281 |
/* 15 bit offset from the zero data area pointer. */ |
/* 15 bit offset from the zero data area pointer. */ |
282 |
HOWTO (R_V850_ZDA_15_16_OFFSET, /* type */ |
HOWTO (R_V850_ZDA_15_16_OFFSET, /* type */ |
283 |
1, /* rightshift */ |
1, /* rightshift */ |
284 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
285 |
16, /* bitsize */ |
16, /* bitsize */ |
286 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
287 |
1, /* bitpos */ |
1, /* bitpos */ |
288 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
289 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
290 |
"R_V850_ZDA_15_16_OFFSET", /* name */ |
"R_V850_ZDA_15_16_OFFSET", /* name */ |
291 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
292 |
0xfffe, /* src_mask */ |
0xfffe, /* src_mask */ |
293 |
0xfffe, /* dst_mask */ |
0xfffe, /* dst_mask */ |
294 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
295 |
|
|
296 |
/* 6 bit offset from the tiny data area pointer. */ |
/* 6 bit offset from the tiny data area pointer. */ |
297 |
HOWTO (R_V850_TDA_6_8_OFFSET, /* type */ |
HOWTO (R_V850_TDA_6_8_OFFSET, /* type */ |
298 |
2, /* rightshift */ |
2, /* rightshift */ |
299 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
300 |
8, /* bitsize */ |
8, /* bitsize */ |
301 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
302 |
1, /* bitpos */ |
1, /* bitpos */ |
303 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
304 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
305 |
"R_V850_TDA_6_8_OFFSET", /* name */ |
"R_V850_TDA_6_8_OFFSET", /* name */ |
306 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
307 |
0x7e, /* src_mask */ |
0x7e, /* src_mask */ |
308 |
0x7e, /* dst_mask */ |
0x7e, /* dst_mask */ |
309 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
310 |
|
|
311 |
/* 8 bit offset from the tiny data area pointer. */ |
/* 8 bit offset from the tiny data area pointer. */ |
312 |
HOWTO (R_V850_TDA_7_8_OFFSET, /* type */ |
HOWTO (R_V850_TDA_7_8_OFFSET, /* type */ |
313 |
1, /* rightshift */ |
1, /* rightshift */ |
314 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
315 |
8, /* bitsize */ |
8, /* bitsize */ |
316 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
317 |
0, /* bitpos */ |
0, /* bitpos */ |
318 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
319 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
320 |
"R_V850_TDA_7_8_OFFSET", /* name */ |
"R_V850_TDA_7_8_OFFSET", /* name */ |
321 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
322 |
0x7f, /* src_mask */ |
0x7f, /* src_mask */ |
323 |
0x7f, /* dst_mask */ |
0x7f, /* dst_mask */ |
324 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
325 |
|
|
326 |
/* 7 bit offset from the tiny data area pointer. */ |
/* 7 bit offset from the tiny data area pointer. */ |
327 |
HOWTO (R_V850_TDA_7_7_OFFSET, /* type */ |
HOWTO (R_V850_TDA_7_7_OFFSET, /* type */ |
328 |
0, /* rightshift */ |
0, /* rightshift */ |
329 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
330 |
7, /* bitsize */ |
7, /* bitsize */ |
331 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
332 |
0, /* bitpos */ |
0, /* bitpos */ |
333 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
334 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
335 |
"R_V850_TDA_7_7_OFFSET", /* name */ |
"R_V850_TDA_7_7_OFFSET", /* name */ |
336 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
337 |
0x7f, /* src_mask */ |
0x7f, /* src_mask */ |
338 |
0x7f, /* dst_mask */ |
0x7f, /* dst_mask */ |
339 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
340 |
|
|
341 |
/* 16 bit offset from the tiny data area pointer! */ |
/* 16 bit offset from the tiny data area pointer! */ |
342 |
HOWTO (R_V850_TDA_16_16_OFFSET, /* type */ |
HOWTO (R_V850_TDA_16_16_OFFSET, /* type */ |
343 |
0, /* rightshift */ |
0, /* rightshift */ |
344 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
345 |
16, /* bitsize */ |
16, /* bitsize */ |
346 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
347 |
0, /* bitpos */ |
0, /* bitpos */ |
348 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
349 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
350 |
"R_V850_TDA_16_16_OFFSET", /* name */ |
"R_V850_TDA_16_16_OFFSET", /* name */ |
351 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
352 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
353 |
0xfff, /* dst_mask */ |
0xfff, /* dst_mask */ |
354 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
355 |
|
|
356 |
/* 5 bit offset from the tiny data area pointer. */ |
/* 5 bit offset from the tiny data area pointer. */ |
357 |
HOWTO (R_V850_TDA_4_5_OFFSET, /* type */ |
HOWTO (R_V850_TDA_4_5_OFFSET, /* type */ |
358 |
1, /* rightshift */ |
1, /* rightshift */ |
359 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
360 |
5, /* bitsize */ |
5, /* bitsize */ |
361 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
362 |
0, /* bitpos */ |
0, /* bitpos */ |
363 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
364 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
365 |
"R_V850_TDA_4_5_OFFSET", /* name */ |
"R_V850_TDA_4_5_OFFSET", /* name */ |
366 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
367 |
0x0f, /* src_mask */ |
0x0f, /* src_mask */ |
368 |
0x0f, /* dst_mask */ |
0x0f, /* dst_mask */ |
369 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
370 |
|
|
371 |
/* 4 bit offset from the tiny data area pointer. */ |
/* 4 bit offset from the tiny data area pointer. */ |
372 |
HOWTO (R_V850_TDA_4_4_OFFSET, /* type */ |
HOWTO (R_V850_TDA_4_4_OFFSET, /* type */ |
373 |
0, /* rightshift */ |
0, /* rightshift */ |
374 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
375 |
4, /* bitsize */ |
4, /* bitsize */ |
376 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
377 |
0, /* bitpos */ |
0, /* bitpos */ |
378 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
379 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
380 |
"R_V850_TDA_4_4_OFFSET", /* name */ |
"R_V850_TDA_4_4_OFFSET", /* name */ |
381 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
382 |
0x0f, /* src_mask */ |
0x0f, /* src_mask */ |
383 |
0x0f, /* dst_mask */ |
0x0f, /* dst_mask */ |
384 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
385 |
|
|
386 |
/* 16 bit offset from the short data area pointer. */ |
/* 16 bit offset from the short data area pointer. */ |
387 |
HOWTO (R_V850_SDA_16_16_SPLIT_OFFSET, /* type */ |
HOWTO (R_V850_SDA_16_16_SPLIT_OFFSET, /* type */ |
388 |
0, /* rightshift */ |
0, /* rightshift */ |
389 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
390 |
16, /* bitsize */ |
16, /* bitsize */ |
391 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
392 |
0, /* bitpos */ |
0, /* bitpos */ |
393 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
394 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
395 |
"R_V850_SDA_16_16_SPLIT_OFFSET",/* name */ |
"R_V850_SDA_16_16_SPLIT_OFFSET",/* name */ |
396 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
397 |
0xfffe0020, /* src_mask */ |
0xfffe0020, /* src_mask */ |
398 |
0xfffe0020, /* dst_mask */ |
0xfffe0020, /* dst_mask */ |
399 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
400 |
|
|
401 |
/* 16 bit offset from the zero data area pointer. */ |
/* 16 bit offset from the zero data area pointer. */ |
402 |
HOWTO (R_V850_ZDA_16_16_SPLIT_OFFSET, /* type */ |
HOWTO (R_V850_ZDA_16_16_SPLIT_OFFSET, /* type */ |
403 |
0, /* rightshift */ |
0, /* rightshift */ |
404 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
405 |
16, /* bitsize */ |
16, /* bitsize */ |
406 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
407 |
0, /* bitpos */ |
0, /* bitpos */ |
408 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
409 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
410 |
"R_V850_ZDA_16_16_SPLIT_OFFSET",/* name */ |
"R_V850_ZDA_16_16_SPLIT_OFFSET",/* name */ |
411 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
412 |
0xfffe0020, /* src_mask */ |
0xfffe0020, /* src_mask */ |
413 |
0xfffe0020, /* dst_mask */ |
0xfffe0020, /* dst_mask */ |
414 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
415 |
|
|
416 |
/* 6 bit offset from the call table base pointer. */ |
/* 6 bit offset from the call table base pointer. */ |
417 |
HOWTO (R_V850_CALLT_6_7_OFFSET, /* type */ |
HOWTO (R_V850_CALLT_6_7_OFFSET, /* type */ |
418 |
0, /* rightshift */ |
0, /* rightshift */ |
419 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
420 |
7, /* bitsize */ |
7, /* bitsize */ |
421 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
422 |
0, /* bitpos */ |
0, /* bitpos */ |
423 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
424 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
425 |
"R_V850_CALLT_6_7_OFFSET", /* name */ |
"R_V850_CALLT_6_7_OFFSET", /* name */ |
426 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
427 |
0x3f, /* src_mask */ |
0x3f, /* src_mask */ |
428 |
0x3f, /* dst_mask */ |
0x3f, /* dst_mask */ |
429 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
430 |
|
|
431 |
/* 16 bit offset from the call table base pointer. */ |
/* 16 bit offset from the call table base pointer. */ |
432 |
HOWTO (R_V850_CALLT_16_16_OFFSET, /* type */ |
HOWTO (R_V850_CALLT_16_16_OFFSET, /* type */ |
433 |
0, /* rightshift */ |
0, /* rightshift */ |
434 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
435 |
16, /* bitsize */ |
16, /* bitsize */ |
436 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
437 |
0, /* bitpos */ |
0, /* bitpos */ |
438 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
439 |
v850_elf_reloc, /* special_function */ |
v850_elf_reloc, /* special_function */ |
440 |
"R_V850_CALLT_16_16_OFFSET", /* name */ |
"R_V850_CALLT_16_16_OFFSET", /* name */ |
441 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
442 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
443 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
444 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
445 |
|
|
446 |
/* GNU extension to record C++ vtable hierarchy */ |
/* GNU extension to record C++ vtable hierarchy */ |
447 |
HOWTO (R_V850_GNU_VTINHERIT, /* type */ |
HOWTO (R_V850_GNU_VTINHERIT, /* type */ |
448 |
0, /* rightshift */ |
0, /* rightshift */ |
449 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
450 |
0, /* bitsize */ |
0, /* bitsize */ |
451 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
452 |
0, /* bitpos */ |
0, /* bitpos */ |
453 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
454 |
NULL, /* special_function */ |
NULL, /* special_function */ |
455 |
"R_V850_GNU_VTINHERIT", /* name */ |
"R_V850_GNU_VTINHERIT", /* name */ |
456 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
457 |
0, /* src_mask */ |
0, /* src_mask */ |
458 |
0, /* dst_mask */ |
0, /* dst_mask */ |
459 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
460 |
|
|
461 |
/* GNU extension to record C++ vtable member usage */ |
/* GNU extension to record C++ vtable member usage */ |
462 |
HOWTO (R_V850_GNU_VTENTRY, /* type */ |
HOWTO (R_V850_GNU_VTENTRY, /* type */ |
463 |
0, /* rightshift */ |
0, /* rightshift */ |
464 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
465 |
0, /* bitsize */ |
0, /* bitsize */ |
466 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
467 |
0, /* bitpos */ |
0, /* bitpos */ |
468 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
469 |
_bfd_elf_rel_vtable_reloc_fn, /* special_function */ |
_bfd_elf_rel_vtable_reloc_fn, /* special_function */ |
470 |
"R_V850_GNU_VTENTRY", /* name */ |
"R_V850_GNU_VTENTRY", /* name */ |
471 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
472 |
0, /* src_mask */ |
0, /* src_mask */ |
473 |
0, /* dst_mask */ |
0, /* dst_mask */ |
474 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
475 |
|
|
476 |
|
/* Indicates a .longcall pseudo-op. The compiler will generate a .longcall |
477 |
|
pseudo-op when it finds a function call which can be relaxed. */ |
478 |
|
HOWTO (R_V850_LONGCALL, /* type */ |
479 |
|
0, /* rightshift */ |
480 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
481 |
|
32, /* bitsize */ |
482 |
|
TRUE, /* pc_relative */ |
483 |
|
0, /* bitpos */ |
484 |
|
complain_overflow_signed, /* complain_on_overflow */ |
485 |
|
v850_elf_ignore_reloc, /* special_function */ |
486 |
|
"R_V850_LONGCALL", /* name */ |
487 |
|
FALSE, /* partial_inplace */ |
488 |
|
0, /* src_mask */ |
489 |
|
0, /* dst_mask */ |
490 |
|
TRUE), /* pcrel_offset */ |
491 |
|
|
492 |
|
/* Indicates a .longjump pseudo-op. The compiler will generate a |
493 |
|
.longjump pseudo-op when it finds a branch which can be relaxed. */ |
494 |
|
HOWTO (R_V850_LONGJUMP, /* type */ |
495 |
|
0, /* rightshift */ |
496 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
497 |
|
32, /* bitsize */ |
498 |
|
TRUE, /* pc_relative */ |
499 |
|
0, /* bitpos */ |
500 |
|
complain_overflow_signed, /* complain_on_overflow */ |
501 |
|
v850_elf_ignore_reloc, /* special_function */ |
502 |
|
"R_V850_LONGJUMP", /* name */ |
503 |
|
FALSE, /* partial_inplace */ |
504 |
|
0, /* src_mask */ |
505 |
|
0, /* dst_mask */ |
506 |
|
TRUE), /* pcrel_offset */ |
507 |
|
|
508 |
|
HOWTO (R_V850_ALIGN, /* type */ |
509 |
|
0, /* rightshift */ |
510 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
511 |
|
0, /* bitsize */ |
512 |
|
FALSE, /* pc_relative */ |
513 |
|
0, /* bitpos */ |
514 |
|
complain_overflow_unsigned, /* complain_on_overflow */ |
515 |
|
v850_elf_ignore_reloc, /* special_function */ |
516 |
|
"R_V850_ALIGN", /* name */ |
517 |
|
FALSE, /* partial_inplace */ |
518 |
|
0, /* src_mask */ |
519 |
|
0, /* dst_mask */ |
520 |
|
TRUE), /* pcrel_offset */ |
521 |
|
|
522 |
|
/* Simple pc-relative 32bit reloc. */ |
523 |
|
HOWTO (R_V850_REL32, /* type */ |
524 |
|
0, /* rightshift */ |
525 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
526 |
|
32, /* bitsize */ |
527 |
|
TRUE, /* pc_relative */ |
528 |
|
0, /* bitpos */ |
529 |
|
complain_overflow_dont, /* complain_on_overflow */ |
530 |
|
v850_elf_reloc, /* special_function */ |
531 |
|
"R_V850_REL32", /* name */ |
532 |
|
FALSE, /* partial_inplace */ |
533 |
|
0xffffffff, /* src_mask */ |
534 |
|
0xffffffff, /* dst_mask */ |
535 |
|
FALSE), /* pcrel_offset */ |
536 |
|
|
537 |
|
/* An ld.bu version of R_V850_LO16. */ |
538 |
|
HOWTO (R_V850_LO16_SPLIT_OFFSET, /* type */ |
539 |
|
0, /* rightshift */ |
540 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
541 |
|
16, /* bitsize */ |
542 |
|
FALSE, /* pc_relative */ |
543 |
|
0, /* bitpos */ |
544 |
|
complain_overflow_dont, /* complain_on_overflow */ |
545 |
|
v850_elf_reloc, /* special_function */ |
546 |
|
"R_V850_LO16_SPLIT_OFFSET", /* name */ |
547 |
|
FALSE, /* partial_inplace */ |
548 |
|
0xfffe0020, /* src_mask */ |
549 |
|
0xfffe0020, /* dst_mask */ |
550 |
|
FALSE), /* pcrel_offset */ |
551 |
}; |
}; |
552 |
|
|
553 |
/* Map BFD reloc types to V850 ELF reloc types. */ |
/* Map BFD reloc types to V850 ELF reloc types. */ |
562 |
|
|
563 |
static const struct v850_elf_reloc_map v850_elf_reloc_map[] = |
static const struct v850_elf_reloc_map v850_elf_reloc_map[] = |
564 |
{ |
{ |
565 |
{ BFD_RELOC_NONE, R_V850_NONE }, |
{ BFD_RELOC_NONE, R_V850_NONE }, |
566 |
{ BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL }, |
{ BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL }, |
567 |
{ BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL }, |
{ BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL }, |
568 |
{ BFD_RELOC_HI16_S, R_V850_HI16_S }, |
{ BFD_RELOC_HI16_S, R_V850_HI16_S }, |
569 |
{ BFD_RELOC_HI16, R_V850_HI16 }, |
{ BFD_RELOC_HI16, R_V850_HI16 }, |
570 |
{ BFD_RELOC_LO16, R_V850_LO16 }, |
{ BFD_RELOC_LO16, R_V850_LO16 }, |
571 |
{ BFD_RELOC_32, R_V850_32 }, |
{ BFD_RELOC_32, R_V850_ABS32 }, |
572 |
{ BFD_RELOC_16, R_V850_16 }, |
{ BFD_RELOC_32_PCREL, R_V850_REL32 }, |
573 |
{ BFD_RELOC_8, R_V850_8 }, |
{ BFD_RELOC_16, R_V850_16 }, |
574 |
{ BFD_RELOC_V850_SDA_16_16_OFFSET, R_V850_SDA_16_16_OFFSET }, |
{ BFD_RELOC_8, R_V850_8 }, |
575 |
{ BFD_RELOC_V850_SDA_15_16_OFFSET, R_V850_SDA_15_16_OFFSET }, |
{ BFD_RELOC_V850_SDA_16_16_OFFSET, R_V850_SDA_16_16_OFFSET }, |
576 |
{ BFD_RELOC_V850_ZDA_16_16_OFFSET, R_V850_ZDA_16_16_OFFSET }, |
{ BFD_RELOC_V850_SDA_15_16_OFFSET, R_V850_SDA_15_16_OFFSET }, |
577 |
{ BFD_RELOC_V850_ZDA_15_16_OFFSET, R_V850_ZDA_15_16_OFFSET }, |
{ BFD_RELOC_V850_ZDA_16_16_OFFSET, R_V850_ZDA_16_16_OFFSET }, |
578 |
{ BFD_RELOC_V850_TDA_6_8_OFFSET, R_V850_TDA_6_8_OFFSET }, |
{ BFD_RELOC_V850_ZDA_15_16_OFFSET, R_V850_ZDA_15_16_OFFSET }, |
579 |
{ BFD_RELOC_V850_TDA_7_8_OFFSET, R_V850_TDA_7_8_OFFSET }, |
{ BFD_RELOC_V850_TDA_6_8_OFFSET, R_V850_TDA_6_8_OFFSET }, |
580 |
{ BFD_RELOC_V850_TDA_7_7_OFFSET, R_V850_TDA_7_7_OFFSET }, |
{ BFD_RELOC_V850_TDA_7_8_OFFSET, R_V850_TDA_7_8_OFFSET }, |
581 |
{ BFD_RELOC_V850_TDA_16_16_OFFSET, R_V850_TDA_16_16_OFFSET }, |
{ BFD_RELOC_V850_TDA_7_7_OFFSET, R_V850_TDA_7_7_OFFSET }, |
582 |
|
{ BFD_RELOC_V850_TDA_16_16_OFFSET, R_V850_TDA_16_16_OFFSET }, |
583 |
{ BFD_RELOC_V850_TDA_4_5_OFFSET, R_V850_TDA_4_5_OFFSET }, |
{ BFD_RELOC_V850_TDA_4_5_OFFSET, R_V850_TDA_4_5_OFFSET }, |
584 |
{ BFD_RELOC_V850_TDA_4_4_OFFSET, R_V850_TDA_4_4_OFFSET }, |
{ BFD_RELOC_V850_TDA_4_4_OFFSET, R_V850_TDA_4_4_OFFSET }, |
585 |
|
{ BFD_RELOC_V850_LO16_SPLIT_OFFSET, R_V850_LO16_SPLIT_OFFSET }, |
586 |
{ BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, R_V850_SDA_16_16_SPLIT_OFFSET }, |
{ BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, R_V850_SDA_16_16_SPLIT_OFFSET }, |
587 |
{ BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, R_V850_ZDA_16_16_SPLIT_OFFSET }, |
{ BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, R_V850_ZDA_16_16_SPLIT_OFFSET }, |
588 |
{ BFD_RELOC_V850_CALLT_6_7_OFFSET, R_V850_CALLT_6_7_OFFSET }, |
{ BFD_RELOC_V850_CALLT_6_7_OFFSET, R_V850_CALLT_6_7_OFFSET }, |
589 |
{ BFD_RELOC_V850_CALLT_16_16_OFFSET, R_V850_CALLT_16_16_OFFSET }, |
{ BFD_RELOC_V850_CALLT_16_16_OFFSET, R_V850_CALLT_16_16_OFFSET }, |
590 |
{ BFD_RELOC_VTABLE_INHERIT, R_V850_GNU_VTINHERIT }, |
{ BFD_RELOC_VTABLE_INHERIT, R_V850_GNU_VTINHERIT }, |
591 |
{ BFD_RELOC_VTABLE_ENTRY, R_V850_GNU_VTENTRY }, |
{ BFD_RELOC_VTABLE_ENTRY, R_V850_GNU_VTENTRY }, |
592 |
|
{ BFD_RELOC_V850_LONGCALL, R_V850_LONGCALL }, |
593 |
|
{ BFD_RELOC_V850_LONGJUMP, R_V850_LONGJUMP }, |
594 |
|
{ BFD_RELOC_V850_ALIGN, R_V850_ALIGN }, |
595 |
|
|
596 |
}; |
}; |
597 |
|
|
599 |
|
|
600 |
static reloc_howto_type * |
static reloc_howto_type * |
601 |
v850_elf_reloc_type_lookup (abfd, code) |
v850_elf_reloc_type_lookup (abfd, code) |
602 |
bfd * abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
603 |
bfd_reloc_code_real_type code; |
bfd_reloc_code_real_type code; |
604 |
{ |
{ |
605 |
unsigned int i; |
unsigned int i; |
606 |
|
|
621 |
|
|
622 |
static void |
static void |
623 |
v850_elf_info_to_howto_rel (abfd, cache_ptr, dst) |
v850_elf_info_to_howto_rel (abfd, cache_ptr, dst) |
624 |
bfd * abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
625 |
arelent * cache_ptr; |
arelent *cache_ptr; |
626 |
Elf32_Internal_Rel * dst; |
Elf_Internal_Rela *dst; |
627 |
{ |
{ |
628 |
unsigned int r_type; |
unsigned int r_type; |
629 |
|
|
635 |
/* Set the howto pointer for a V850 ELF reloc (type RELA). */ |
/* Set the howto pointer for a V850 ELF reloc (type RELA). */ |
636 |
static void |
static void |
637 |
v850_elf_info_to_howto_rela (abfd, cache_ptr, dst) |
v850_elf_info_to_howto_rela (abfd, cache_ptr, dst) |
638 |
bfd * abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
639 |
arelent * cache_ptr; |
arelent * cache_ptr; |
640 |
Elf32_Internal_Rela *dst; |
Elf_Internal_Rela *dst; |
641 |
{ |
{ |
642 |
unsigned int r_type; |
unsigned int r_type; |
643 |
|
|
650 |
allocate space in the global offset table or procedure linkage |
allocate space in the global offset table or procedure linkage |
651 |
table. */ |
table. */ |
652 |
|
|
653 |
static boolean |
static bfd_boolean |
654 |
v850_elf_check_relocs (abfd, info, sec, relocs) |
v850_elf_check_relocs (abfd, info, sec, relocs) |
655 |
bfd * abfd; |
bfd *abfd; |
656 |
struct bfd_link_info * info; |
struct bfd_link_info *info; |
657 |
asection * sec; |
asection *sec; |
658 |
const Elf_Internal_Rela * relocs; |
const Elf_Internal_Rela *relocs; |
659 |
{ |
{ |
660 |
boolean ret = true; |
bfd_boolean ret = TRUE; |
661 |
bfd *dynobj; |
bfd *dynobj; |
662 |
Elf_Internal_Shdr *symtab_hdr; |
Elf_Internal_Shdr *symtab_hdr; |
663 |
struct elf_link_hash_entry **sym_hashes; |
struct elf_link_hash_entry **sym_hashes; |
668 |
int other = 0; |
int other = 0; |
669 |
const char *common = (const char *)0; |
const char *common = (const char *)0; |
670 |
|
|
671 |
if (info->relocateable) |
if (info->relocatable) |
672 |
return true; |
return TRUE; |
673 |
|
|
674 |
#ifdef DEBUG |
#ifdef DEBUG |
675 |
fprintf (stderr, "v850_elf_check_relocs called for section %s in %s\n", |
_bfd_error_handler ("v850_elf_check_relocs called for section %A in %B", |
676 |
bfd_get_section_name (abfd, sec), |
sec, abfd); |
|
bfd_archive_filename (abfd)); |
|
677 |
#endif |
#endif |
678 |
|
|
679 |
dynobj = elf_hash_table (info)->dynobj; |
dynobj = elf_hash_table (info)->dynobj; |
703 |
case R_V850_HI16_S: |
case R_V850_HI16_S: |
704 |
case R_V850_HI16: |
case R_V850_HI16: |
705 |
case R_V850_LO16: |
case R_V850_LO16: |
706 |
case R_V850_32: |
case R_V850_LO16_SPLIT_OFFSET: |
707 |
|
case R_V850_ABS32: |
708 |
|
case R_V850_REL32: |
709 |
case R_V850_16: |
case R_V850_16: |
710 |
case R_V850_8: |
case R_V850_8: |
711 |
case R_V850_CALLT_6_7_OFFSET: |
case R_V850_CALLT_6_7_OFFSET: |
715 |
/* This relocation describes the C++ object vtable hierarchy. |
/* This relocation describes the C++ object vtable hierarchy. |
716 |
Reconstruct it for later use during GC. */ |
Reconstruct it for later use during GC. */ |
717 |
case R_V850_GNU_VTINHERIT: |
case R_V850_GNU_VTINHERIT: |
718 |
if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) |
if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) |
719 |
return false; |
return FALSE; |
720 |
break; |
break; |
721 |
|
|
722 |
/* This relocation describes which C++ vtable entries |
/* This relocation describes which C++ vtable entries |
723 |
are actually used. Record for later use during GC. */ |
are actually used. Record for later use during GC. */ |
724 |
case R_V850_GNU_VTENTRY: |
case R_V850_GNU_VTENTRY: |
725 |
if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) |
if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) |
726 |
return false; |
return FALSE; |
727 |
break; |
break; |
728 |
|
|
729 |
case R_V850_SDA_16_16_SPLIT_OFFSET: |
case R_V850_SDA_16_16_SPLIT_OFFSET: |
789 |
|
|
790 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
791 |
h->other |= V850_OTHER_ERROR; |
h->other |= V850_OTHER_ERROR; |
792 |
ret = false; |
ret = FALSE; |
793 |
} |
} |
794 |
} |
} |
795 |
|
|
821 |
more than once, as the second attempted retry failed. |
more than once, as the second attempted retry failed. |
822 |
|
|
823 |
In the current version, the entry is not deleted, instead we set |
In the current version, the entry is not deleted, instead we set |
824 |
the field 'found' to true. If a second lookup matches the same |
the field 'found' to TRUE. If a second lookup matches the same |
825 |
entry, then we know that the hi16s reloc has already been updated |
entry, then we know that the hi16s reloc has already been updated |
826 |
and does not need to be updated a second time. |
and does not need to be updated a second time. |
827 |
|
|
831 |
|
|
832 |
typedef struct hi16s_location |
typedef struct hi16s_location |
833 |
{ |
{ |
834 |
bfd_vma addend; |
bfd_vma addend; |
835 |
bfd_byte * address; |
bfd_byte *address; |
836 |
unsigned long counter; |
unsigned long counter; |
837 |
boolean found; |
bfd_boolean found; |
838 |
struct hi16s_location * next; |
struct hi16s_location *next; |
839 |
} |
} |
840 |
hi16s_location; |
hi16s_location; |
841 |
|
|
842 |
static hi16s_location * previous_hi16s; |
static hi16s_location *previous_hi16s; |
843 |
static hi16s_location * free_hi16s; |
static hi16s_location *free_hi16s; |
844 |
static unsigned long hi16s_counter; |
static unsigned long hi16s_counter; |
845 |
|
|
846 |
static void |
static void |
847 |
remember_hi16s_reloc (abfd, addend, address) |
remember_hi16s_reloc (abfd, addend, address) |
848 |
bfd * abfd; |
bfd *abfd; |
849 |
bfd_vma addend; |
bfd_vma addend; |
850 |
bfd_byte * address; |
bfd_byte *address; |
851 |
{ |
{ |
852 |
hi16s_location * entry = NULL; |
hi16s_location * entry = NULL; |
853 |
bfd_size_type amt = sizeof (* free_hi16s); |
bfd_size_type amt = sizeof (* free_hi16s); |
862 |
entry->addend = addend; |
entry->addend = addend; |
863 |
entry->address = address; |
entry->address = address; |
864 |
entry->counter = hi16s_counter ++; |
entry->counter = hi16s_counter ++; |
865 |
entry->found = false; |
entry->found = FALSE; |
866 |
entry->next = previous_hi16s; |
entry->next = previous_hi16s; |
867 |
previous_hi16s = entry; |
previous_hi16s = entry; |
868 |
|
|
881 |
|
|
882 |
static bfd_byte * |
static bfd_byte * |
883 |
find_remembered_hi16s_reloc (addend, already_found) |
find_remembered_hi16s_reloc (addend, already_found) |
884 |
bfd_vma addend; |
bfd_vma addend; |
885 |
boolean * already_found; |
bfd_boolean *already_found; |
886 |
{ |
{ |
887 |
hi16s_location * match = NULL; |
hi16s_location *match = NULL; |
888 |
hi16s_location * entry; |
hi16s_location *entry; |
889 |
hi16s_location * previous = NULL; |
hi16s_location *previous = NULL; |
890 |
hi16s_location * prev; |
hi16s_location *prev; |
891 |
bfd_byte * addr; |
bfd_byte *addr; |
892 |
|
|
893 |
/* Search the table. Record the most recent entry that matches. */ |
/* Search the table. Record the most recent entry that matches. */ |
894 |
for (entry = previous_hi16s; entry; entry = entry->next) |
for (entry = previous_hi16s; entry; entry = entry->next) |
909 |
/* Extract the address. */ |
/* Extract the address. */ |
910 |
addr = match->address; |
addr = match->address; |
911 |
|
|
912 |
/* Remeber if this entry has already been used before. */ |
/* Remember if this entry has already been used before. */ |
913 |
if (already_found) |
if (already_found) |
914 |
* already_found = match->found; |
* already_found = match->found; |
915 |
|
|
916 |
/* Note that this entry has now been used. */ |
/* Note that this entry has now been used. */ |
917 |
match->found = true; |
match->found = TRUE; |
918 |
|
|
919 |
return addr; |
return addr; |
920 |
} |
} |
921 |
|
|
922 |
|
/* Calculate the final operand value for a R_V850_LO16 or |
923 |
|
R_V850_LO16_SPLIT_OFFSET. *INSN is the current operand value and |
924 |
|
ADDEND is the sum of the relocation symbol and offset. Store the |
925 |
|
operand value in *INSN and return true on success. |
926 |
|
|
927 |
|
The assembler has already done some of this: If the value stored in |
928 |
|
the instruction has its 15th bit set, (counting from zero) then the |
929 |
|
assembler will have added 1 to the value stored in the associated |
930 |
|
HI16S reloc. So for example, these relocations: |
931 |
|
|
932 |
|
movhi hi( fred ), r0, r1 |
933 |
|
movea lo( fred ), r1, r1 |
934 |
|
|
935 |
|
will store 0 in the value fields for the MOVHI and MOVEA instructions |
936 |
|
and addend will be the address of fred, but for these instructions: |
937 |
|
|
938 |
|
movhi hi( fred + 0x123456), r0, r1 |
939 |
|
movea lo( fred + 0x123456), r1, r1 |
940 |
|
|
941 |
|
the value stored in the MOVHI instruction will be 0x12 and the value |
942 |
|
stored in the MOVEA instruction will be 0x3456. If however the |
943 |
|
instructions were: |
944 |
|
|
945 |
|
movhi hi( fred + 0x10ffff), r0, r1 |
946 |
|
movea lo( fred + 0x10ffff), r1, r1 |
947 |
|
|
948 |
|
then the value stored in the MOVHI instruction would be 0x11 (not |
949 |
|
0x10) and the value stored in the MOVEA instruction would be 0xffff. |
950 |
|
Thus (assuming for the moment that the addend is 0), at run time the |
951 |
|
MOVHI instruction loads 0x110000 into r1, then the MOVEA instruction |
952 |
|
adds 0xffffffff (sign extension!) producing 0x10ffff. Similarly if |
953 |
|
the instructions were: |
954 |
|
|
955 |
|
movhi hi( fred - 1), r0, r1 |
956 |
|
movea lo( fred - 1), r1, r1 |
957 |
|
|
958 |
|
then 0 is stored in the MOVHI instruction and -1 is stored in the |
959 |
|
MOVEA instruction. |
960 |
|
|
961 |
|
Overflow can occur if the addition of the value stored in the |
962 |
|
instruction plus the addend sets the 15th bit when before it was clear. |
963 |
|
This is because the 15th bit will be sign extended into the high part, |
964 |
|
thus reducing its value by one, but since the 15th bit was originally |
965 |
|
clear, the assembler will not have added 1 to the previous HI16S reloc |
966 |
|
to compensate for this effect. For example: |
967 |
|
|
968 |
|
movhi hi( fred + 0x123456), r0, r1 |
969 |
|
movea lo( fred + 0x123456), r1, r1 |
970 |
|
|
971 |
|
The value stored in HI16S reloc is 0x12, the value stored in the LO16 |
972 |
|
reloc is 0x3456. If we assume that the address of fred is 0x00007000 |
973 |
|
then the relocations become: |
974 |
|
|
975 |
|
HI16S: 0x0012 + (0x00007000 >> 16) = 0x12 |
976 |
|
LO16: 0x3456 + (0x00007000 & 0xffff) = 0xa456 |
977 |
|
|
978 |
|
but when the instructions are executed, the MOVEA instruction's value |
979 |
|
is signed extended, so the sum becomes: |
980 |
|
|
981 |
|
0x00120000 |
982 |
|
+ 0xffffa456 |
983 |
|
------------ |
984 |
|
0x0011a456 but 'fred + 0x123456' = 0x0012a456 |
985 |
|
|
986 |
|
Note that if the 15th bit was set in the value stored in the LO16 |
987 |
|
reloc, then we do not have to do anything: |
988 |
|
|
989 |
|
movhi hi( fred + 0x10ffff), r0, r1 |
990 |
|
movea lo( fred + 0x10ffff), r1, r1 |
991 |
|
|
992 |
|
HI16S: 0x0011 + (0x00007000 >> 16) = 0x11 |
993 |
|
LO16: 0xffff + (0x00007000 & 0xffff) = 0x6fff |
994 |
|
|
995 |
|
0x00110000 |
996 |
|
+ 0x00006fff |
997 |
|
------------ |
998 |
|
0x00116fff = fred + 0x10ffff = 0x7000 + 0x10ffff |
999 |
|
|
1000 |
|
Overflow can also occur if the computation carries into the 16th bit |
1001 |
|
and it also results in the 15th bit having the same value as the 15th |
1002 |
|
bit of the original value. What happens is that the HI16S reloc |
1003 |
|
will have already examined the 15th bit of the original value and |
1004 |
|
added 1 to the high part if the bit is set. This compensates for the |
1005 |
|
sign extension of 15th bit of the result of the computation. But now |
1006 |
|
there is a carry into the 16th bit, and this has not been allowed for. |
1007 |
|
|
1008 |
|
So, for example if fred is at address 0xf000: |
1009 |
|
|
1010 |
|
movhi hi( fred + 0xffff), r0, r1 [bit 15 of the offset is set] |
1011 |
|
movea lo( fred + 0xffff), r1, r1 |
1012 |
|
|
1013 |
|
HI16S: 0x0001 + (0x0000f000 >> 16) = 0x0001 |
1014 |
|
LO16: 0xffff + (0x0000f000 & 0xffff) = 0xefff (carry into bit 16 is lost) |
1015 |
|
|
1016 |
|
0x00010000 |
1017 |
|
+ 0xffffefff |
1018 |
|
------------ |
1019 |
|
0x0000efff but 'fred + 0xffff' = 0x0001efff |
1020 |
|
|
1021 |
|
Similarly, if the 15th bit remains clear, but overflow occurs into |
1022 |
|
the 16th bit then (assuming the address of fred is 0xf000): |
1023 |
|
|
1024 |
|
movhi hi( fred + 0x7000), r0, r1 [bit 15 of the offset is clear] |
1025 |
|
movea lo( fred + 0x7000), r1, r1 |
1026 |
|
|
1027 |
|
HI16S: 0x0000 + (0x0000f000 >> 16) = 0x0000 |
1028 |
|
LO16: 0x7000 + (0x0000f000 & 0xffff) = 0x6fff (carry into bit 16 is lost) |
1029 |
|
|
1030 |
|
0x00000000 |
1031 |
|
+ 0x00006fff |
1032 |
|
------------ |
1033 |
|
0x00006fff but 'fred + 0x7000' = 0x00016fff |
1034 |
|
|
1035 |
|
Note - there is no need to change anything if a carry occurs, and the |
1036 |
|
15th bit changes its value from being set to being clear, as the HI16S |
1037 |
|
reloc will have already added in 1 to the high part for us: |
1038 |
|
|
1039 |
|
movhi hi( fred + 0xffff), r0, r1 [bit 15 of the offset is set] |
1040 |
|
movea lo( fred + 0xffff), r1, r1 |
1041 |
|
|
1042 |
|
HI16S: 0x0001 + (0x00007000 >> 16) |
1043 |
|
LO16: 0xffff + (0x00007000 & 0xffff) = 0x6fff (carry into bit 16 is lost) |
1044 |
|
|
1045 |
|
0x00010000 |
1046 |
|
+ 0x00006fff (bit 15 not set, so the top half is zero) |
1047 |
|
------------ |
1048 |
|
0x00016fff which is right (assuming that fred is at 0x7000) |
1049 |
|
|
1050 |
|
but if the 15th bit goes from being clear to being set, then we must |
1051 |
|
once again handle overflow: |
1052 |
|
|
1053 |
|
movhi hi( fred + 0x7000), r0, r1 [bit 15 of the offset is clear] |
1054 |
|
movea lo( fred + 0x7000), r1, r1 |
1055 |
|
|
1056 |
|
HI16S: 0x0000 + (0x0000ffff >> 16) |
1057 |
|
LO16: 0x7000 + (0x0000ffff & 0xffff) = 0x6fff (carry into bit 16) |
1058 |
|
|
1059 |
|
0x00000000 |
1060 |
|
+ 0x00006fff (bit 15 not set, so the top half is zero) |
1061 |
|
------------ |
1062 |
|
0x00006fff which is wrong (assuming that fred is at 0xffff). */ |
1063 |
|
|
1064 |
|
static bfd_boolean |
1065 |
|
v850_elf_perform_lo16_relocation (bfd *abfd, unsigned long *insn, |
1066 |
|
unsigned long addend) |
1067 |
|
{ |
1068 |
|
#define BIT15_SET(x) ((x) & 0x8000) |
1069 |
|
#define OVERFLOWS(a,i) ((((a) & 0xffff) + (i)) > 0xffff) |
1070 |
|
if ((BIT15_SET (*insn + addend) && ! BIT15_SET (addend)) |
1071 |
|
|| (OVERFLOWS (addend, *insn) |
1072 |
|
&& ((! BIT15_SET (*insn)) || (BIT15_SET (addend))))) |
1073 |
|
{ |
1074 |
|
bfd_boolean already_updated; |
1075 |
|
bfd_byte *hi16s_address = find_remembered_hi16s_reloc |
1076 |
|
(addend, & already_updated); |
1077 |
|
|
1078 |
|
/* Amend the matching HI16_S relocation. */ |
1079 |
|
if (hi16s_address != NULL) |
1080 |
|
{ |
1081 |
|
if (! already_updated) |
1082 |
|
{ |
1083 |
|
unsigned long hi_insn = bfd_get_16 (abfd, hi16s_address); |
1084 |
|
hi_insn += 1; |
1085 |
|
bfd_put_16 (abfd, hi_insn, hi16s_address); |
1086 |
|
} |
1087 |
|
} |
1088 |
|
else |
1089 |
|
{ |
1090 |
|
fprintf (stderr, _("FAILED to find previous HI16 reloc\n")); |
1091 |
|
return FALSE; |
1092 |
|
} |
1093 |
|
} |
1094 |
|
#undef OVERFLOWS |
1095 |
|
#undef BIT15_SET |
1096 |
|
|
1097 |
|
/* Do not complain if value has top bit set, as this has been |
1098 |
|
anticipated. */ |
1099 |
|
*insn = (*insn + addend) & 0xffff; |
1100 |
|
return TRUE; |
1101 |
|
} |
1102 |
|
|
1103 |
/* FIXME: The code here probably ought to be removed and the code in reloc.c |
/* FIXME: The code here probably ought to be removed and the code in reloc.c |
1104 |
allowed to do its stuff instead. At least for most of the relocs, anwyay. */ |
allowed to do its stuff instead. At least for most of the relocs, anyway. */ |
1105 |
|
|
1106 |
static bfd_reloc_status_type |
static bfd_reloc_status_type |
1107 |
v850_elf_perform_relocation (abfd, r_type, addend, address) |
v850_elf_perform_relocation (abfd, r_type, addend, address) |
1111 |
bfd_byte *address; |
bfd_byte *address; |
1112 |
{ |
{ |
1113 |
unsigned long insn; |
unsigned long insn; |
1114 |
|
unsigned long result; |
1115 |
bfd_signed_vma saddend = (bfd_signed_vma) addend; |
bfd_signed_vma saddend = (bfd_signed_vma) addend; |
1116 |
|
|
1117 |
switch (r_type) |
switch (r_type) |
1120 |
/* fprintf (stderr, "reloc type %d not SUPPORTED\n", r_type ); */ |
/* fprintf (stderr, "reloc type %d not SUPPORTED\n", r_type ); */ |
1121 |
return bfd_reloc_notsupported; |
return bfd_reloc_notsupported; |
1122 |
|
|
1123 |
case R_V850_32: |
case R_V850_REL32: |
1124 |
|
case R_V850_ABS32: |
1125 |
bfd_put_32 (abfd, addend, address); |
bfd_put_32 (abfd, addend, address); |
1126 |
return bfd_reloc_ok; |
return bfd_reloc_ok; |
1127 |
|
|
1171 |
break; |
break; |
1172 |
|
|
1173 |
case R_V850_LO16: |
case R_V850_LO16: |
1174 |
/* Calculate the sum of the value stored in the instruction and the |
insn = bfd_get_16 (abfd, address); |
1175 |
addend and check for overflow from the low 16 bits into the high |
if (! v850_elf_perform_lo16_relocation (abfd, &insn, addend)) |
1176 |
16 bits. The assembler has already done some of this: If the |
return bfd_reloc_overflow; |
1177 |
value stored in the instruction has its 15th bit set, (counting |
break; |
|
from zero) then the assembler will have added 1 to the value |
|
|
stored in the associated HI16S reloc. So for example, these |
|
|
relocations: |
|
|
|
|
|
movhi hi( fred ), r0, r1 |
|
|
movea lo( fred ), r1, r1 |
|
|
|
|
|
will store 0 in the value fields for the MOVHI and MOVEA instructions |
|
|
and addend will be the address of fred, but for these instructions: |
|
|
|
|
|
movhi hi( fred + 0x123456), r0, r1 |
|
|
movea lo( fred + 0x123456), r1, r1 |
|
|
|
|
|
the value stored in the MOVHI instruction will be 0x12 and the value |
|
|
stored in the MOVEA instruction will be 0x3456. If however the |
|
|
instructions were: |
|
|
|
|
|
movhi hi( fred + 0x10ffff), r0, r1 |
|
|
movea lo( fred + 0x10ffff), r1, r1 |
|
|
|
|
|
then the value stored in the MOVHI instruction would be 0x11 (not |
|
|
0x10) and the value stored in the MOVEA instruction would be 0xffff. |
|
|
Thus (assuming for the moment that the addend is 0), at run time the |
|
|
MOVHI instruction loads 0x110000 into r1, then the MOVEA instruction |
|
|
adds 0xffffffff (sign extension!) producing 0x10ffff. Similarly if |
|
|
the instructions were: |
|
|
|
|
|
movhi hi( fred - 1), r0, r1 |
|
|
movea lo( fred - 1), r1, r1 |
|
|
|
|
|
then 0 is stored in the MOVHI instruction and -1 is stored in the |
|
|
MOVEA instruction. |
|
|
|
|
|
Overflow can occur if the addition of the value stored in the |
|
|
instruction plus the addend sets the 15th bit when before it was clear. |
|
|
This is because the 15th bit will be sign extended into the high part, |
|
|
thus reducing its value by one, but since the 15th bit was originally |
|
|
clear, the assembler will not have added 1 to the previous HI16S reloc |
|
|
to compensate for this effect. For example: |
|
|
|
|
|
movhi hi( fred + 0x123456), r0, r1 |
|
|
movea lo( fred + 0x123456), r1, r1 |
|
|
|
|
|
The value stored in HI16S reloc is 0x12, the value stored in the LO16 |
|
|
reloc is 0x3456. If we assume that the address of fred is 0x00007000 |
|
|
then the relocations become: |
|
|
|
|
|
HI16S: 0x0012 + (0x00007000 >> 16) = 0x12 |
|
|
LO16: 0x3456 + (0x00007000 & 0xffff) = 0xa456 |
|
|
|
|
|
but when the instructions are executed, the MOVEA instruction's value |
|
|
is signed extended, so the sum becomes: |
|
|
|
|
|
0x00120000 |
|
|
+ 0xffffa456 |
|
|
------------ |
|
|
0x0011a456 but 'fred + 0x123456' = 0x0012a456 |
|
|
|
|
|
Note that if the 15th bit was set in the value stored in the LO16 |
|
|
reloc, then we do not have to do anything: |
|
|
|
|
|
movhi hi( fred + 0x10ffff), r0, r1 |
|
|
movea lo( fred + 0x10ffff), r1, r1 |
|
|
|
|
|
HI16S: 0x0011 + (0x00007000 >> 16) = 0x11 |
|
|
LO16: 0xffff + (0x00007000 & 0xffff) = 0x6fff |
|
|
|
|
|
0x00110000 |
|
|
+ 0x00006fff |
|
|
------------ |
|
|
0x00116fff = fred + 0x10ffff = 0x7000 + 0x10ffff |
|
|
|
|
|
Overflow can also occur if the computation carries into the 16th bit |
|
|
and it also results in the 15th bit having the same value as the 15th |
|
|
bit of the original value. What happens is that the HI16S reloc |
|
|
will have already examined the 15th bit of the original value and |
|
|
added 1 to the high part if the bit is set. This compensates for the |
|
|
sign extension of 15th bit of the result of the computation. But now |
|
|
there is a carry into the 16th bit, and this has not been allowed for. |
|
|
|
|
|
So, for example if fred is at address 0xf000: |
|
|
|
|
|
movhi hi( fred + 0xffff), r0, r1 [bit 15 of the offset is set] |
|
|
movea lo( fred + 0xffff), r1, r1 |
|
|
|
|
|
HI16S: 0x0001 + (0x0000f000 >> 16) = 0x0001 |
|
|
LO16: 0xffff + (0x0000f000 & 0xffff) = 0xefff (carry into bit 16 is lost) |
|
|
|
|
|
0x00010000 |
|
|
+ 0xffffefff |
|
|
------------ |
|
|
0x0000efff but 'fred + 0xffff' = 0x0001efff |
|
|
|
|
|
Similarly, if the 15th bit remains clear, but overflow occurs into |
|
|
the 16th bit then (assuming the address of fred is 0xf000): |
|
|
|
|
|
movhi hi( fred + 0x7000), r0, r1 [bit 15 of the offset is clear] |
|
|
movea lo( fred + 0x7000), r1, r1 |
|
|
|
|
|
HI16S: 0x0000 + (0x0000f000 >> 16) = 0x0000 |
|
|
LO16: 0x7000 + (0x0000f000 & 0xffff) = 0x6fff (carry into bit 16 is lost) |
|
|
|
|
|
0x00000000 |
|
|
+ 0x00006fff |
|
|
------------ |
|
|
0x00006fff but 'fred + 0x7000' = 0x00016fff |
|
|
|
|
|
Note - there is no need to change anything if a carry occurs, and the |
|
|
15th bit changes its value from being set to being clear, as the HI16S |
|
|
reloc will have already added in 1 to the high part for us: |
|
|
|
|
|
movhi hi( fred + 0xffff), r0, r1 [bit 15 of the offset is set] |
|
|
movea lo( fred + 0xffff), r1, r1 |
|
|
|
|
|
HI16S: 0x0001 + (0x00007000 >> 16) |
|
|
LO16: 0xffff + (0x00007000 & 0xffff) = 0x6fff (carry into bit 16 is lost) |
|
|
|
|
|
0x00010000 |
|
|
+ 0x00006fff (bit 15 not set, so the top half is zero) |
|
|
------------ |
|
|
0x00016fff which is right (assuming that fred is at 0x7000) |
|
|
|
|
|
but if the 15th bit goes from being clear to being set, then we must |
|
|
once again handle overflow: |
|
|
|
|
|
movhi hi( fred + 0x7000), r0, r1 [bit 15 of the offset is clear] |
|
|
movea lo( fred + 0x7000), r1, r1 |
|
|
|
|
|
HI16S: 0x0000 + (0x0000ffff >> 16) |
|
|
LO16: 0x7000 + (0x0000ffff & 0xffff) = 0x6fff (carry into bit 16) |
|
|
|
|
|
0x00000000 |
|
|
+ 0x00006fff (bit 15 not set, so the top half is zero) |
|
|
------------ |
|
|
0x00006fff which is wrong (assuming that fred is at 0xffff). */ |
|
|
{ |
|
|
long result; |
|
|
|
|
|
insn = bfd_get_16 (abfd, address); |
|
|
result = insn + addend; |
|
|
|
|
|
#define BIT15_SET(x) ((x) & 0x8000) |
|
|
#define OVERFLOWS(a,i) ((((a) & 0xffff) + (i)) > 0xffff) |
|
|
|
|
|
if ((BIT15_SET (result) && ! BIT15_SET (addend)) |
|
|
|| (OVERFLOWS (addend, insn) |
|
|
&& ((! BIT15_SET (insn)) || (BIT15_SET (addend))))) |
|
|
{ |
|
|
boolean already_updated; |
|
|
bfd_byte * hi16s_address = find_remembered_hi16s_reloc |
|
|
(addend, & already_updated); |
|
|
|
|
|
/* Amend the matching HI16_S relocation. */ |
|
|
if (hi16s_address != NULL) |
|
|
{ |
|
|
if (! already_updated) |
|
|
{ |
|
|
insn = bfd_get_16 (abfd, hi16s_address); |
|
|
insn += 1; |
|
|
bfd_put_16 (abfd, (bfd_vma) insn, hi16s_address); |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
fprintf (stderr, _("FAILED to find previous HI16 reloc\n")); |
|
|
return bfd_reloc_overflow; |
|
|
} |
|
|
} |
|
|
|
|
|
/* Do not complain if value has top bit set, as this has been anticipated. */ |
|
|
insn = result & 0xffff; |
|
|
break; |
|
|
} |
|
1178 |
|
|
1179 |
case R_V850_8: |
case R_V850_8: |
1180 |
addend += (char) bfd_get_8 (abfd, address); |
addend += (char) bfd_get_8 (abfd, address); |
1304 |
insn |= addend; |
insn |= addend; |
1305 |
break; |
break; |
1306 |
|
|
1307 |
|
case R_V850_LO16_SPLIT_OFFSET: |
1308 |
|
insn = bfd_get_32 (abfd, address); |
1309 |
|
result = ((insn & 0xfffe0000) >> 16) | ((insn & 0x20) >> 5); |
1310 |
|
if (! v850_elf_perform_lo16_relocation (abfd, &result, addend)) |
1311 |
|
return bfd_reloc_overflow; |
1312 |
|
insn = (((result << 16) & 0xfffe0000) |
1313 |
|
| ((result << 5) & 0x20) |
1314 |
|
| (insn & ~0xfffe0020)); |
1315 |
|
bfd_put_32 (abfd, insn, address); |
1316 |
|
return bfd_reloc_ok; |
1317 |
|
|
1318 |
case R_V850_ZDA_16_16_SPLIT_OFFSET: |
case R_V850_ZDA_16_16_SPLIT_OFFSET: |
1319 |
case R_V850_SDA_16_16_SPLIT_OFFSET: |
case R_V850_SDA_16_16_SPLIT_OFFSET: |
1320 |
insn = bfd_get_32 (abfd, address); |
insn = bfd_get_32 (abfd, address); |
1362 |
|
|
1363 |
static bfd_reloc_status_type |
static bfd_reloc_status_type |
1364 |
v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err) |
v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err) |
1365 |
bfd * abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
1366 |
arelent * reloc; |
arelent *reloc; |
1367 |
asymbol * symbol; |
asymbol *symbol; |
1368 |
PTR data ATTRIBUTE_UNUSED; |
PTR data ATTRIBUTE_UNUSED; |
1369 |
asection * isection; |
asection *isection; |
1370 |
bfd * obfd; |
bfd *obfd; |
1371 |
char ** err ATTRIBUTE_UNUSED; |
char **err ATTRIBUTE_UNUSED; |
1372 |
{ |
{ |
1373 |
long relocation; |
long relocation; |
1374 |
|
|
1385 |
reloc->address += isection->output_offset; |
reloc->address += isection->output_offset; |
1386 |
return bfd_reloc_ok; |
return bfd_reloc_ok; |
1387 |
} |
} |
|
#if 0 |
|
|
else if (obfd != NULL) |
|
|
return bfd_reloc_continue; |
|
|
#endif |
|
1388 |
|
|
1389 |
/* Catch relocs involving undefined symbols. */ |
/* Catch relocs involving undefined symbols. */ |
1390 |
if (bfd_is_und_section (symbol->section) |
if (bfd_is_und_section (symbol->section) |
1395 |
/* We handle final linking of some relocs ourselves. */ |
/* We handle final linking of some relocs ourselves. */ |
1396 |
|
|
1397 |
/* Is the address of the relocation really within the section? */ |
/* Is the address of the relocation really within the section? */ |
1398 |
if (reloc->address > isection->_cooked_size) |
if (reloc->address > bfd_get_section_limit (abfd, isection)) |
1399 |
return bfd_reloc_outofrange; |
return bfd_reloc_outofrange; |
1400 |
|
|
1401 |
/* Work out which section the relocation is targetted at and the |
/* Work out which section the relocation is targeted at and the |
1402 |
initial relocation command value. */ |
initial relocation command value. */ |
1403 |
|
|
1404 |
|
if (reloc->howto->pc_relative) |
1405 |
|
return bfd_reloc_ok; |
1406 |
|
|
1407 |
/* Get symbol value. (Common symbols are special.) */ |
/* Get symbol value. (Common symbols are special.) */ |
1408 |
if (bfd_is_com_section (symbol->section)) |
if (bfd_is_com_section (symbol->section)) |
1409 |
relocation = 0; |
relocation = 0; |
1415 |
relocation += symbol->section->output_offset; |
relocation += symbol->section->output_offset; |
1416 |
relocation += reloc->addend; |
relocation += reloc->addend; |
1417 |
|
|
|
#if 0 /* Since this reloc is going to be processed later on, we should |
|
|
not make it pc-relative here. To test this, try assembling and |
|
|
linking this program: |
|
|
|
|
|
.text |
|
|
.globl _start |
|
|
nop |
|
|
_start: |
|
|
jr foo |
|
|
|
|
|
.section ".foo","ax" |
|
|
nop |
|
|
foo: |
|
|
nop */ |
|
|
if (reloc->howto->pc_relative) |
|
|
{ |
|
|
/* Here the variable relocation holds the final address of the |
|
|
symbol we are relocating against, plus any addend. */ |
|
|
relocation -= isection->output_section->vma + isection->output_offset; |
|
|
|
|
|
/* Deal with pcrel_offset. */ |
|
|
relocation -= reloc->address; |
|
|
} |
|
|
#endif |
|
1418 |
reloc->addend = relocation; |
reloc->addend = relocation; |
1419 |
return bfd_reloc_ok; |
return bfd_reloc_ok; |
1420 |
} |
} |
1421 |
|
|
1422 |
|
/* This function is used for relocs which are only used |
1423 |
|
for relaxing, which the linker should otherwise ignore. */ |
1424 |
|
|
1425 |
|
static bfd_reloc_status_type |
1426 |
|
v850_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section, |
1427 |
|
output_bfd, error_message) |
1428 |
|
bfd *abfd ATTRIBUTE_UNUSED; |
1429 |
|
arelent *reloc_entry; |
1430 |
|
asymbol *symbol ATTRIBUTE_UNUSED; |
1431 |
|
PTR data ATTRIBUTE_UNUSED; |
1432 |
|
asection *input_section; |
1433 |
|
bfd *output_bfd; |
1434 |
|
char **error_message ATTRIBUTE_UNUSED; |
1435 |
|
{ |
1436 |
|
if (output_bfd != NULL) |
1437 |
|
reloc_entry->address += input_section->output_offset; |
1438 |
|
|
1439 |
|
return bfd_reloc_ok; |
1440 |
|
} |
1441 |
|
|
1442 |
static boolean |
static bfd_boolean |
1443 |
v850_elf_is_local_label_name (abfd, name) |
v850_elf_is_local_label_name (abfd, name) |
1444 |
bfd * abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
1445 |
const char * name; |
const char *name; |
1446 |
{ |
{ |
1447 |
return ( (name[0] == '.' && (name[1] == 'L' || name[1] == '.')) |
return ( (name[0] == '.' && (name[1] == 'L' || name[1] == '.')) |
1448 |
|| (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')); |
|| (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')); |
1449 |
} |
} |
1450 |
|
|
1451 |
|
/* We overload some of the bfd_reloc error codes for own purposes. */ |
1452 |
|
#define bfd_reloc_gp_not_found bfd_reloc_other |
1453 |
|
#define bfd_reloc_ep_not_found bfd_reloc_continue |
1454 |
|
#define bfd_reloc_ctbp_not_found (bfd_reloc_dangerous + 1) |
1455 |
|
|
1456 |
/* Perform a relocation as part of a final link. */ |
/* Perform a relocation as part of a final link. */ |
1457 |
|
|
1458 |
static bfd_reloc_status_type |
static bfd_reloc_status_type |
1459 |
v850_elf_final_link_relocate (howto, input_bfd, output_bfd, |
v850_elf_final_link_relocate (howto, input_bfd, output_bfd, |
1460 |
input_section, contents, offset, value, |
input_section, contents, offset, value, |
1461 |
addend, info, sym_sec, is_local) |
addend, info, sym_sec, is_local) |
1462 |
reloc_howto_type * howto; |
reloc_howto_type *howto; |
1463 |
bfd * input_bfd; |
bfd *input_bfd; |
1464 |
bfd * output_bfd ATTRIBUTE_UNUSED; |
bfd *output_bfd ATTRIBUTE_UNUSED; |
1465 |
asection * input_section; |
asection *input_section; |
1466 |
bfd_byte * contents; |
bfd_byte *contents; |
1467 |
bfd_vma offset; |
bfd_vma offset; |
1468 |
bfd_vma value; |
bfd_vma value; |
1469 |
bfd_vma addend; |
bfd_vma addend; |
1470 |
struct bfd_link_info * info; |
struct bfd_link_info *info; |
1471 |
asection * sym_sec; |
asection *sym_sec; |
1472 |
int is_local ATTRIBUTE_UNUSED; |
int is_local ATTRIBUTE_UNUSED; |
1473 |
{ |
{ |
1474 |
unsigned int r_type = howto->type; |
unsigned int r_type = howto->type; |
1475 |
bfd_byte * hit_data = contents + offset; |
bfd_byte *hit_data = contents + offset; |
1476 |
|
|
1477 |
/* Adjust the value according to the relocation. */ |
/* Adjust the value according to the relocation. */ |
1478 |
switch (r_type) |
switch (r_type) |
1496 |
value = SEXT24 (value); |
value = SEXT24 (value); |
1497 |
break; |
break; |
1498 |
|
|
1499 |
|
case R_V850_REL32: |
1500 |
|
value -= (input_section->output_section->vma |
1501 |
|
+ input_section->output_offset |
1502 |
|
+ offset); |
1503 |
|
break; |
1504 |
|
|
1505 |
case R_V850_HI16_S: |
case R_V850_HI16_S: |
1506 |
case R_V850_HI16: |
case R_V850_HI16: |
1507 |
case R_V850_LO16: |
case R_V850_LO16: |
1508 |
|
case R_V850_LO16_SPLIT_OFFSET: |
1509 |
case R_V850_16: |
case R_V850_16: |
1510 |
case R_V850_32: |
case R_V850_ABS32: |
1511 |
case R_V850_8: |
case R_V850_8: |
1512 |
break; |
break; |
1513 |
|
|
1531 |
return bfd_reloc_undefined; |
return bfd_reloc_undefined; |
1532 |
|
|
1533 |
/* Get the value of __gp. */ |
/* Get the value of __gp. */ |
1534 |
h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true); |
h = bfd_link_hash_lookup (info->hash, "__gp", FALSE, FALSE, TRUE); |
1535 |
if (h == (struct bfd_link_hash_entry *) NULL |
if (h == (struct bfd_link_hash_entry *) NULL |
1536 |
|| h->type != bfd_link_hash_defined) |
|| h->type != bfd_link_hash_defined) |
1537 |
return bfd_reloc_other; |
return bfd_reloc_gp_not_found; |
1538 |
|
|
1539 |
gp = (h->u.def.value |
gp = (h->u.def.value |
1540 |
+ h->u.def.section->output_section->vma |
+ h->u.def.section->output_section->vma |
1556 |
struct bfd_link_hash_entry * h; |
struct bfd_link_hash_entry * h; |
1557 |
|
|
1558 |
/* Get the value of __ep. */ |
/* Get the value of __ep. */ |
1559 |
h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true); |
h = bfd_link_hash_lookup (info->hash, "__ep", FALSE, FALSE, TRUE); |
1560 |
if (h == (struct bfd_link_hash_entry *) NULL |
if (h == (struct bfd_link_hash_entry *) NULL |
1561 |
|| h->type != bfd_link_hash_defined) |
|| h->type != bfd_link_hash_defined) |
1562 |
/* Actually this indicates that __ep could not be found. */ |
return bfd_reloc_ep_not_found; |
|
return bfd_reloc_continue; |
|
1563 |
|
|
1564 |
ep = (h->u.def.value |
ep = (h->u.def.value |
1565 |
+ h->u.def.section->output_section->vma |
+ h->u.def.section->output_section->vma |
1575 |
struct bfd_link_hash_entry * h; |
struct bfd_link_hash_entry * h; |
1576 |
|
|
1577 |
/* Get the value of __ctbp. */ |
/* Get the value of __ctbp. */ |
1578 |
h = bfd_link_hash_lookup (info->hash, "__ctbp", false, false, true); |
h = bfd_link_hash_lookup (info->hash, "__ctbp", FALSE, FALSE, TRUE); |
1579 |
if (h == (struct bfd_link_hash_entry *) NULL |
if (h == (struct bfd_link_hash_entry *) NULL |
1580 |
|| h->type != bfd_link_hash_defined) |
|| h->type != bfd_link_hash_defined) |
1581 |
/* Actually this indicates that __ctbp could not be found. */ |
return bfd_reloc_ctbp_not_found; |
|
return bfd_reloc_dangerous + 1; |
|
1582 |
|
|
1583 |
ctbp = (h->u.def.value |
ctbp = (h->u.def.value |
1584 |
+ h->u.def.section->output_section->vma |
+ h->u.def.section->output_section->vma |
1596 |
return bfd_reloc_undefined; |
return bfd_reloc_undefined; |
1597 |
|
|
1598 |
/* Get the value of __ctbp. */ |
/* Get the value of __ctbp. */ |
1599 |
h = bfd_link_hash_lookup (info->hash, "__ctbp", false, false, true); |
h = bfd_link_hash_lookup (info->hash, "__ctbp", FALSE, FALSE, TRUE); |
1600 |
if (h == (struct bfd_link_hash_entry *) NULL |
if (h == (struct bfd_link_hash_entry *) NULL |
1601 |
|| h->type != bfd_link_hash_defined) |
|| h->type != bfd_link_hash_defined) |
1602 |
return (bfd_reloc_dangerous + 1); |
return bfd_reloc_ctbp_not_found; |
1603 |
|
|
1604 |
ctbp = (h->u.def.value |
ctbp = (h->u.def.value |
1605 |
+ h->u.def.section->output_section->vma |
+ h->u.def.section->output_section->vma |
1613 |
case R_V850_NONE: |
case R_V850_NONE: |
1614 |
case R_V850_GNU_VTINHERIT: |
case R_V850_GNU_VTINHERIT: |
1615 |
case R_V850_GNU_VTENTRY: |
case R_V850_GNU_VTENTRY: |
1616 |
|
case R_V850_LONGCALL: |
1617 |
|
case R_V850_LONGJUMP: |
1618 |
|
case R_V850_ALIGN: |
1619 |
return bfd_reloc_ok; |
return bfd_reloc_ok; |
1620 |
|
|
1621 |
default: |
default: |
1628 |
|
|
1629 |
/* Relocate an V850 ELF section. */ |
/* Relocate an V850 ELF section. */ |
1630 |
|
|
1631 |
static boolean |
static bfd_boolean |
1632 |
v850_elf_relocate_section (output_bfd, info, input_bfd, input_section, |
v850_elf_relocate_section (output_bfd, info, input_bfd, input_section, |
1633 |
contents, relocs, local_syms, local_sections) |
contents, relocs, local_syms, local_sections) |
1634 |
bfd * output_bfd; |
bfd *output_bfd; |
1635 |
struct bfd_link_info * info; |
struct bfd_link_info *info; |
1636 |
bfd * input_bfd; |
bfd *input_bfd; |
1637 |
asection * input_section; |
asection *input_section; |
1638 |
bfd_byte * contents; |
bfd_byte *contents; |
1639 |
Elf_Internal_Rela * relocs; |
Elf_Internal_Rela *relocs; |
1640 |
Elf_Internal_Sym * local_syms; |
Elf_Internal_Sym *local_syms; |
1641 |
asection ** local_sections; |
asection **local_sections; |
1642 |
{ |
{ |
1643 |
Elf_Internal_Shdr * symtab_hdr; |
Elf_Internal_Shdr *symtab_hdr; |
1644 |
struct elf_link_hash_entry ** sym_hashes; |
struct elf_link_hash_entry **sym_hashes; |
1645 |
Elf_Internal_Rela * rel; |
Elf_Internal_Rela *rel; |
1646 |
Elf_Internal_Rela * relend; |
Elf_Internal_Rela *relend; |
1647 |
|
|
1648 |
|
if (info->relocatable) |
1649 |
|
return TRUE; |
1650 |
|
|
1651 |
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; |
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; |
1652 |
sym_hashes = elf_sym_hashes (input_bfd); |
sym_hashes = elf_sym_hashes (input_bfd); |
1657 |
(info, "no hash table available", |
(info, "no hash table available", |
1658 |
NULL, input_bfd, input_section, (bfd_vma) 0); |
NULL, input_bfd, input_section, (bfd_vma) 0); |
1659 |
|
|
1660 |
return false; |
return FALSE; |
1661 |
} |
} |
1662 |
|
|
1663 |
/* Reset the list of remembered HI16S relocs to empty. */ |
/* Reset the list of remembered HI16S relocs to empty. */ |
1669 |
relend = relocs + input_section->reloc_count; |
relend = relocs + input_section->reloc_count; |
1670 |
for (; rel < relend; rel++) |
for (; rel < relend; rel++) |
1671 |
{ |
{ |
1672 |
int r_type; |
int r_type; |
1673 |
reloc_howto_type * howto; |
reloc_howto_type *howto; |
1674 |
unsigned long r_symndx; |
unsigned long r_symndx; |
1675 |
Elf_Internal_Sym * sym; |
Elf_Internal_Sym *sym; |
1676 |
asection * sec; |
asection *sec; |
1677 |
struct elf_link_hash_entry * h; |
struct elf_link_hash_entry *h; |
1678 |
bfd_vma relocation; |
bfd_vma relocation; |
1679 |
bfd_reloc_status_type r; |
bfd_reloc_status_type r; |
1680 |
|
|
1681 |
r_symndx = ELF32_R_SYM (rel->r_info); |
r_symndx = ELF32_R_SYM (rel->r_info); |
1682 |
r_type = ELF32_R_TYPE (rel->r_info); |
r_type = ELF32_R_TYPE (rel->r_info); |
1685 |
|| r_type == R_V850_GNU_VTINHERIT) |
|| r_type == R_V850_GNU_VTINHERIT) |
1686 |
continue; |
continue; |
1687 |
|
|
|
howto = v850_elf_howto_table + r_type; |
|
|
|
|
|
if (info->relocateable) |
|
|
{ |
|
|
/* This is a relocateable link. We don't have to change |
|
|
anything, unless the reloc is against a section symbol, |
|
|
in which case we have to adjust according to where the |
|
|
section symbol winds up in the output section. */ |
|
|
if (r_symndx < symtab_hdr->sh_info) |
|
|
{ |
|
|
sym = local_syms + r_symndx; |
|
|
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) |
|
|
{ |
|
|
sec = local_sections[r_symndx]; |
|
|
rel->r_addend += sec->output_offset + sym->st_value; |
|
|
} |
|
|
} |
|
|
|
|
|
continue; |
|
|
} |
|
|
|
|
1688 |
/* This is a final link. */ |
/* This is a final link. */ |
1689 |
|
howto = v850_elf_howto_table + r_type; |
1690 |
h = NULL; |
h = NULL; |
1691 |
sym = NULL; |
sym = NULL; |
1692 |
sec = NULL; |
sec = NULL; |
1694 |
{ |
{ |
1695 |
sym = local_syms + r_symndx; |
sym = local_syms + r_symndx; |
1696 |
sec = local_sections[r_symndx]; |
sec = local_sections[r_symndx]; |
1697 |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); |
|
#if 0 |
|
|
{ |
|
|
char * name; |
|
|
|
|
|
name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name); |
|
|
name = (name == NULL) ? "<none>" : name; |
|
|
fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n", |
|
|
sec->name, name, sym->st_name, |
|
|
sec->output_section->vma, sec->output_offset, sym->st_value, rel->r_addend); |
|
|
} |
|
|
#endif |
|
1698 |
} |
} |
1699 |
else |
else |
1700 |
{ |
{ |
1701 |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
bfd_boolean unresolved_reloc, warned; |
|
|
|
|
while (h->root.type == bfd_link_hash_indirect |
|
|
|| h->root.type == bfd_link_hash_warning) |
|
|
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
|
1702 |
|
|
1703 |
if (h->root.type == bfd_link_hash_defined |
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, |
1704 |
|| h->root.type == bfd_link_hash_defweak) |
r_symndx, symtab_hdr, sym_hashes, |
1705 |
{ |
h, sec, relocation, |
1706 |
sec = h->root.u.def.section; |
unresolved_reloc, warned); |
|
relocation = (h->root.u.def.value |
|
|
+ sec->output_section->vma |
|
|
+ sec->output_offset); |
|
|
#if 0 |
|
|
fprintf (stderr, "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n", |
|
|
sec->name, h->root.root.string, h->root.u.def.value, sec->output_section->vma, sec->output_offset, relocation); |
|
|
#endif |
|
|
} |
|
|
else if (h->root.type == bfd_link_hash_undefweak) |
|
|
{ |
|
|
#if 0 |
|
|
fprintf (stderr, "undefined: sec: %s, name: %s\n", |
|
|
sec->name, h->root.root.string); |
|
|
#endif |
|
|
relocation = 0; |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (! ((*info->callbacks->undefined_symbol) |
|
|
(info, h->root.root.string, input_bfd, |
|
|
input_section, rel->r_offset, true))) |
|
|
return false; |
|
|
#if 0 |
|
|
fprintf (stderr, "unknown: name: %s\n", h->root.root.string); |
|
|
#endif |
|
|
relocation = 0; |
|
|
} |
|
1707 |
} |
} |
1708 |
|
|
1709 |
/* FIXME: We should use the addend, but the COFF relocations don't. */ |
/* FIXME: We should use the addend, but the COFF relocations don't. */ |
1732 |
{ |
{ |
1733 |
case bfd_reloc_overflow: |
case bfd_reloc_overflow: |
1734 |
if (! ((*info->callbacks->reloc_overflow) |
if (! ((*info->callbacks->reloc_overflow) |
1735 |
(info, name, howto->name, (bfd_vma) 0, |
(info, (h ? &h->root : NULL), name, howto->name, |
1736 |
input_bfd, input_section, rel->r_offset))) |
(bfd_vma) 0, input_bfd, input_section, |
1737 |
return false; |
rel->r_offset))) |
1738 |
|
return FALSE; |
1739 |
break; |
break; |
1740 |
|
|
1741 |
case bfd_reloc_undefined: |
case bfd_reloc_undefined: |
1742 |
if (! ((*info->callbacks->undefined_symbol) |
if (! ((*info->callbacks->undefined_symbol) |
1743 |
(info, name, input_bfd, input_section, |
(info, name, input_bfd, input_section, |
1744 |
rel->r_offset, true))) |
rel->r_offset, TRUE))) |
1745 |
return false; |
return FALSE; |
1746 |
break; |
break; |
1747 |
|
|
1748 |
case bfd_reloc_outofrange: |
case bfd_reloc_outofrange: |
1757 |
msg = _("internal error: dangerous relocation"); |
msg = _("internal error: dangerous relocation"); |
1758 |
goto common_error; |
goto common_error; |
1759 |
|
|
1760 |
case bfd_reloc_other: |
case bfd_reloc_gp_not_found: |
1761 |
msg = _("could not locate special linker symbol __gp"); |
msg = _("could not locate special linker symbol __gp"); |
1762 |
goto common_error; |
goto common_error; |
1763 |
|
|
1764 |
case bfd_reloc_continue: |
case bfd_reloc_ep_not_found: |
1765 |
msg = _("could not locate special linker symbol __ep"); |
msg = _("could not locate special linker symbol __ep"); |
1766 |
goto common_error; |
goto common_error; |
1767 |
|
|
1768 |
case (bfd_reloc_dangerous + 1): |
case bfd_reloc_ctbp_not_found: |
1769 |
msg = _("could not locate special linker symbol __ctbp"); |
msg = _("could not locate special linker symbol __ctbp"); |
1770 |
goto common_error; |
goto common_error; |
1771 |
|
|
1777 |
if (!((*info->callbacks->warning) |
if (!((*info->callbacks->warning) |
1778 |
(info, msg, name, input_bfd, input_section, |
(info, msg, name, input_bfd, input_section, |
1779 |
rel->r_offset))) |
rel->r_offset))) |
1780 |
return false; |
return FALSE; |
1781 |
break; |
break; |
1782 |
} |
} |
1783 |
} |
} |
1784 |
} |
} |
1785 |
|
|
1786 |
return true; |
return TRUE; |
1787 |
} |
} |
1788 |
|
|
1789 |
static boolean |
static bfd_boolean |
1790 |
v850_elf_gc_sweep_hook (abfd, info, sec, relocs) |
v850_elf_gc_sweep_hook (abfd, info, sec, relocs) |
1791 |
bfd *abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
1792 |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
1794 |
const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED; |
const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED; |
1795 |
{ |
{ |
1796 |
/* No got and plt entries for v850-elf. */ |
/* No got and plt entries for v850-elf. */ |
1797 |
return true; |
return TRUE; |
1798 |
} |
} |
1799 |
|
|
1800 |
static asection * |
static asection * |
1836 |
|
|
1837 |
/* Set the right machine number. */ |
/* Set the right machine number. */ |
1838 |
|
|
1839 |
static boolean |
static bfd_boolean |
1840 |
v850_elf_object_p (abfd) |
v850_elf_object_p (abfd) |
1841 |
bfd *abfd; |
bfd *abfd; |
1842 |
{ |
{ |
1843 |
switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH) |
switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH) |
1844 |
{ |
{ |
1845 |
default: |
default: |
1846 |
case E_V850_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, 0); break; |
case E_V850_ARCH: |
1847 |
case E_V850E_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); break; |
bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850); |
1848 |
case E_V850EA_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850ea); break; |
break; |
1849 |
|
case E_V850E_ARCH: |
1850 |
|
bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); |
1851 |
|
break; |
1852 |
|
case E_V850E1_ARCH: |
1853 |
|
bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e1); |
1854 |
|
break; |
1855 |
} |
} |
1856 |
return true; |
return TRUE; |
1857 |
} |
} |
1858 |
|
|
1859 |
/* Store the machine number in the flags field. */ |
/* Store the machine number in the flags field. */ |
1860 |
|
|
1861 |
static void |
static void |
1862 |
v850_elf_final_write_processing (abfd, linker) |
v850_elf_final_write_processing (abfd, linker) |
1863 |
bfd * abfd; |
bfd *abfd; |
1864 |
boolean linker ATTRIBUTE_UNUSED; |
bfd_boolean linker ATTRIBUTE_UNUSED; |
1865 |
{ |
{ |
1866 |
unsigned long val; |
unsigned long val; |
1867 |
|
|
1868 |
switch (bfd_get_mach (abfd)) |
switch (bfd_get_mach (abfd)) |
1869 |
{ |
{ |
1870 |
default: |
default: |
1871 |
case 0: val = E_V850_ARCH; break; |
case bfd_mach_v850: val = E_V850_ARCH; break; |
1872 |
case bfd_mach_v850e: val = E_V850E_ARCH; break; |
case bfd_mach_v850e: val = E_V850E_ARCH; break; |
1873 |
case bfd_mach_v850ea: val = E_V850EA_ARCH; break; |
case bfd_mach_v850e1: val = E_V850E1_ARCH; break; |
1874 |
} |
} |
1875 |
|
|
1876 |
elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH; |
elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH; |
1879 |
|
|
1880 |
/* Function to keep V850 specific file flags. */ |
/* Function to keep V850 specific file flags. */ |
1881 |
|
|
1882 |
static boolean |
static bfd_boolean |
1883 |
v850_elf_set_private_flags (abfd, flags) |
v850_elf_set_private_flags (abfd, flags) |
1884 |
bfd * abfd; |
bfd *abfd; |
1885 |
flagword flags; |
flagword flags; |
1886 |
{ |
{ |
1887 |
BFD_ASSERT (!elf_flags_init (abfd) |
BFD_ASSERT (!elf_flags_init (abfd) |
1888 |
|| elf_elfheader (abfd)->e_flags == flags); |
|| elf_elfheader (abfd)->e_flags == flags); |
1889 |
|
|
1890 |
elf_elfheader (abfd)->e_flags = flags; |
elf_elfheader (abfd)->e_flags = flags; |
1891 |
elf_flags_init (abfd) = true; |
elf_flags_init (abfd) = TRUE; |
1892 |
return true; |
return TRUE; |
1893 |
} |
} |
1894 |
|
|
1895 |
/* Merge backend specific data from an object file |
/* Merge backend specific data from an object file |
1896 |
to the output object file when linking. */ |
to the output object file when linking. */ |
1897 |
static boolean |
static bfd_boolean |
1898 |
v850_elf_merge_private_bfd_data (ibfd, obfd) |
v850_elf_merge_private_bfd_data (ibfd, obfd) |
1899 |
bfd * ibfd; |
bfd *ibfd; |
1900 |
bfd * obfd; |
bfd *obfd; |
1901 |
{ |
{ |
1902 |
flagword out_flags; |
flagword out_flags; |
1903 |
flagword in_flags; |
flagword in_flags; |
1904 |
|
|
1905 |
if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
1906 |
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
1907 |
return true; |
return TRUE; |
1908 |
|
|
1909 |
in_flags = elf_elfheader (ibfd)->e_flags; |
in_flags = elf_elfheader (ibfd)->e_flags; |
1910 |
out_flags = elf_elfheader (obfd)->e_flags; |
out_flags = elf_elfheader (obfd)->e_flags; |
1918 |
unitialised values, which surprise surprise, correspond |
unitialised values, which surprise surprise, correspond |
1919 |
to the default values. */ |
to the default values. */ |
1920 |
if (bfd_get_arch_info (ibfd)->the_default) |
if (bfd_get_arch_info (ibfd)->the_default) |
1921 |
return true; |
return TRUE; |
1922 |
|
|
1923 |
elf_flags_init (obfd) = true; |
elf_flags_init (obfd) = TRUE; |
1924 |
elf_elfheader (obfd)->e_flags = in_flags; |
elf_elfheader (obfd)->e_flags = in_flags; |
1925 |
|
|
1926 |
if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) |
if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) |
1927 |
&& bfd_get_arch_info (obfd)->the_default) |
&& bfd_get_arch_info (obfd)->the_default) |
1928 |
return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd)); |
return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd)); |
1929 |
|
|
1930 |
return true; |
return TRUE; |
1931 |
} |
} |
1932 |
|
|
1933 |
/* Check flag compatibility. */ |
/* Check flag compatibility. */ |
1934 |
if (in_flags == out_flags) |
if (in_flags == out_flags) |
1935 |
return true; |
return TRUE; |
1936 |
|
|
1937 |
if ((in_flags & EF_V850_ARCH) != (out_flags & EF_V850_ARCH) |
if ((in_flags & EF_V850_ARCH) != (out_flags & EF_V850_ARCH) |
1938 |
&& (in_flags & EF_V850_ARCH) != E_V850_ARCH) |
&& (in_flags & EF_V850_ARCH) != E_V850_ARCH) |
1939 |
_bfd_error_handler (_("%s: Architecture mismatch with previous modules"), |
{ |
1940 |
bfd_archive_filename (ibfd)); |
/* Allow v850e1 binaries to be linked with v850e binaries. |
1941 |
|
Set the output binary to v850e. */ |
1942 |
|
if ((in_flags & EF_V850_ARCH) == E_V850E1_ARCH |
1943 |
|
&& (out_flags & EF_V850_ARCH) == E_V850E_ARCH) |
1944 |
|
return TRUE; |
1945 |
|
|
1946 |
|
if ((in_flags & EF_V850_ARCH) == E_V850E_ARCH |
1947 |
|
&& (out_flags & EF_V850_ARCH) == E_V850E1_ARCH) |
1948 |
|
{ |
1949 |
|
elf_elfheader (obfd)->e_flags = |
1950 |
|
((out_flags & ~ EF_V850_ARCH) | E_V850E_ARCH); |
1951 |
|
return TRUE; |
1952 |
|
} |
1953 |
|
|
1954 |
|
_bfd_error_handler (_("%B: Architecture mismatch with previous modules"), |
1955 |
|
ibfd); |
1956 |
|
} |
1957 |
|
|
1958 |
return true; |
return TRUE; |
1959 |
} |
} |
1960 |
|
|
1961 |
/* Display the flags field. */ |
/* Display the flags field. */ |
1962 |
|
|
1963 |
static boolean |
static bfd_boolean |
1964 |
v850_elf_print_private_bfd_data (abfd, ptr) |
v850_elf_print_private_bfd_data (abfd, ptr) |
1965 |
bfd * abfd; |
bfd *abfd; |
1966 |
PTR ptr; |
PTR ptr; |
1967 |
{ |
{ |
1968 |
FILE * file = (FILE *) ptr; |
FILE * file = (FILE *) ptr; |
1969 |
|
|
1979 |
default: |
default: |
1980 |
case E_V850_ARCH: fprintf (file, _("v850 architecture")); break; |
case E_V850_ARCH: fprintf (file, _("v850 architecture")); break; |
1981 |
case E_V850E_ARCH: fprintf (file, _("v850e architecture")); break; |
case E_V850E_ARCH: fprintf (file, _("v850e architecture")); break; |
1982 |
case E_V850EA_ARCH: fprintf (file, _("v850ea architecture")); break; |
case E_V850E1_ARCH: fprintf (file, _("v850e1 architecture")); break; |
1983 |
} |
} |
1984 |
|
|
1985 |
fputc ('\n', file); |
fputc ('\n', file); |
1986 |
|
|
1987 |
return true; |
return TRUE; |
1988 |
} |
} |
1989 |
|
|
1990 |
/* V850 ELF uses four common sections. One is the usual one, and the |
/* V850 ELF uses four common sections. One is the usual one, and the |
2007 |
/* Given a BFD section, try to locate the |
/* Given a BFD section, try to locate the |
2008 |
corresponding ELF section index. */ |
corresponding ELF section index. */ |
2009 |
|
|
2010 |
static boolean |
static bfd_boolean |
2011 |
v850_elf_section_from_bfd_section (abfd, sec, retval) |
v850_elf_section_from_bfd_section (abfd, sec, retval) |
2012 |
bfd * abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
2013 |
asection * sec; |
asection *sec; |
2014 |
int * retval; |
int *retval; |
2015 |
{ |
{ |
2016 |
if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0) |
if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0) |
2017 |
*retval = SHN_V850_SCOMMON; |
*retval = SHN_V850_SCOMMON; |
2020 |
else if (strcmp (bfd_get_section_name (abfd, sec), ".zcommon") == 0) |
else if (strcmp (bfd_get_section_name (abfd, sec), ".zcommon") == 0) |
2021 |
*retval = SHN_V850_ZCOMMON; |
*retval = SHN_V850_ZCOMMON; |
2022 |
else |
else |
2023 |
return false; |
return FALSE; |
2024 |
|
|
2025 |
return true; |
return TRUE; |
2026 |
} |
} |
2027 |
|
|
2028 |
/* Handle the special V850 section numbers that a symbol may use. */ |
/* Handle the special V850 section numbers that a symbol may use. */ |
2029 |
|
|
2030 |
static void |
static void |
2031 |
v850_elf_symbol_processing (abfd, asym) |
v850_elf_symbol_processing (abfd, asym) |
2032 |
bfd * abfd; |
bfd *abfd; |
2033 |
asymbol * asym; |
asymbol *asym; |
2034 |
{ |
{ |
2035 |
elf_symbol_type * elfsym = (elf_symbol_type *) asym; |
elf_symbol_type * elfsym = (elf_symbol_type *) asym; |
2036 |
unsigned int indx; |
unsigned int indx; |
2123 |
/* Hook called by the linker routine which adds symbols from an object |
/* Hook called by the linker routine which adds symbols from an object |
2124 |
file. We must handle the special v850 section numbers here. */ |
file. We must handle the special v850 section numbers here. */ |
2125 |
|
|
2126 |
static boolean |
static bfd_boolean |
2127 |
v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) |
v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) |
2128 |
bfd * abfd; |
bfd *abfd; |
2129 |
struct bfd_link_info * info ATTRIBUTE_UNUSED; |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
2130 |
const Elf_Internal_Sym * sym; |
Elf_Internal_Sym *sym; |
2131 |
const char ** namep ATTRIBUTE_UNUSED; |
const char **namep ATTRIBUTE_UNUSED; |
2132 |
flagword * flagsp ATTRIBUTE_UNUSED; |
flagword *flagsp ATTRIBUTE_UNUSED; |
2133 |
asection ** secp; |
asection **secp; |
2134 |
bfd_vma * valp; |
bfd_vma *valp; |
2135 |
{ |
{ |
2136 |
unsigned int indx = sym->st_shndx; |
unsigned int indx = sym->st_shndx; |
2137 |
|
|
2181 |
break; |
break; |
2182 |
} |
} |
2183 |
|
|
2184 |
return true; |
return TRUE; |
2185 |
} |
} |
2186 |
|
|
2187 |
static boolean |
static bfd_boolean |
2188 |
v850_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec) |
v850_elf_link_output_symbol_hook (info, name, sym, input_sec, h) |
2189 |
bfd * abfd ATTRIBUTE_UNUSED; |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
2190 |
struct bfd_link_info * info ATTRIBUTE_UNUSED; |
const char *name ATTRIBUTE_UNUSED; |
2191 |
const char * name ATTRIBUTE_UNUSED; |
Elf_Internal_Sym *sym; |
2192 |
Elf_Internal_Sym * sym; |
asection *input_sec; |
2193 |
asection * input_sec; |
struct elf_link_hash_entry *h ATTRIBUTE_UNUSED; |
2194 |
{ |
{ |
2195 |
/* If we see a common symbol, which implies a relocatable link, then |
/* If we see a common symbol, which implies a relocatable link, then |
2196 |
if a symbol was in a special common section in an input file, mark |
if a symbol was in a special common section in an input file, mark |
2206 |
sym->st_shndx = SHN_V850_ZCOMMON; |
sym->st_shndx = SHN_V850_ZCOMMON; |
2207 |
} |
} |
2208 |
|
|
2209 |
return true; |
return TRUE; |
2210 |
} |
} |
2211 |
|
|
2212 |
static boolean |
static bfd_boolean |
2213 |
v850_elf_section_from_shdr (abfd, hdr, name) |
v850_elf_section_from_shdr (abfd, hdr, name) |
2214 |
bfd * abfd; |
bfd *abfd; |
2215 |
Elf_Internal_Shdr * hdr; |
Elf_Internal_Shdr *hdr; |
2216 |
const char * name; |
const char *name; |
2217 |
{ |
{ |
2218 |
/* There ought to be a place to keep ELF backend specific flags, but |
/* There ought to be a place to keep ELF backend specific flags, but |
2219 |
at the moment there isn't one. We just keep track of the |
at the moment there isn't one. We just keep track of the |
2220 |
sections by their name, instead. */ |
sections by their name, instead. */ |
2221 |
|
|
2222 |
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) |
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) |
2223 |
return false; |
return FALSE; |
2224 |
|
|
2225 |
switch (hdr->sh_type) |
switch (hdr->sh_type) |
2226 |
{ |
{ |
2231 |
(bfd_get_section_flags (abfd, |
(bfd_get_section_flags (abfd, |
2232 |
hdr->bfd_section) |
hdr->bfd_section) |
2233 |
| SEC_IS_COMMON))) |
| SEC_IS_COMMON))) |
2234 |
return false; |
return FALSE; |
2235 |
} |
} |
2236 |
|
|
2237 |
return true; |
return TRUE; |
2238 |
} |
} |
2239 |
|
|
2240 |
/* Set the correct type for a V850 ELF section. We do this |
/* Set the correct type for a V850 ELF section. We do this |
2241 |
by the section name, which is a hack, but ought to work. */ |
by the section name, which is a hack, but ought to work. */ |
2242 |
|
|
2243 |
static boolean |
static bfd_boolean |
2244 |
v850_elf_fake_sections (abfd, hdr, sec) |
v850_elf_fake_sections (abfd, hdr, sec) |
2245 |
bfd * abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
2246 |
Elf32_Internal_Shdr * hdr; |
Elf_Internal_Shdr *hdr; |
2247 |
asection * sec; |
asection *sec; |
2248 |
{ |
{ |
2249 |
register const char * name; |
register const char * name; |
2250 |
|
|
2261 |
else if (strcmp (name, ".zcommon") == 0) |
else if (strcmp (name, ".zcommon") == 0) |
2262 |
hdr->sh_type = SHT_V850_ZCOMMON; |
hdr->sh_type = SHT_V850_ZCOMMON; |
2263 |
|
|
2264 |
return true; |
return TRUE; |
2265 |
|
} |
2266 |
|
|
2267 |
|
/* Delete some bytes from a section while relaxing. */ |
2268 |
|
|
2269 |
|
static bfd_boolean |
2270 |
|
v850_elf_relax_delete_bytes (abfd, sec, addr, toaddr, count) |
2271 |
|
bfd *abfd; |
2272 |
|
asection *sec; |
2273 |
|
bfd_vma addr; |
2274 |
|
bfd_vma toaddr; |
2275 |
|
int count; |
2276 |
|
{ |
2277 |
|
Elf_Internal_Shdr *symtab_hdr; |
2278 |
|
Elf32_External_Sym *extsyms; |
2279 |
|
Elf32_External_Sym *esym; |
2280 |
|
Elf32_External_Sym *esymend; |
2281 |
|
int index; |
2282 |
|
unsigned int sec_shndx; |
2283 |
|
bfd_byte *contents; |
2284 |
|
Elf_Internal_Rela *irel; |
2285 |
|
Elf_Internal_Rela *irelend; |
2286 |
|
struct elf_link_hash_entry *sym_hash; |
2287 |
|
Elf_Internal_Shdr *shndx_hdr; |
2288 |
|
Elf_External_Sym_Shndx *shndx; |
2289 |
|
|
2290 |
|
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
2291 |
|
extsyms = (Elf32_External_Sym *) symtab_hdr->contents; |
2292 |
|
|
2293 |
|
sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); |
2294 |
|
|
2295 |
|
contents = elf_section_data (sec)->this_hdr.contents; |
2296 |
|
|
2297 |
|
/* The deletion must stop at the next ALIGN reloc for an alignment |
2298 |
|
power larger than the number of bytes we are deleting. */ |
2299 |
|
|
2300 |
|
/* Actually delete the bytes. */ |
2301 |
|
#if (DEBUG_RELAX & 2) |
2302 |
|
fprintf (stderr, "relax_delete: contents: sec: %s %p .. %p %x\n", |
2303 |
|
sec->name, addr, toaddr, count ); |
2304 |
|
#endif |
2305 |
|
memmove (contents + addr, contents + addr + count, |
2306 |
|
toaddr - addr - count); |
2307 |
|
memset (contents + toaddr-count, 0, count); |
2308 |
|
|
2309 |
|
/* Adjust all the relocs. */ |
2310 |
|
irel = elf_section_data (sec)->relocs; |
2311 |
|
irelend = irel + sec->reloc_count; |
2312 |
|
shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; |
2313 |
|
shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents; |
2314 |
|
|
2315 |
|
for (; irel < irelend; irel++) |
2316 |
|
{ |
2317 |
|
bfd_vma raddr, paddr, symval; |
2318 |
|
Elf_Internal_Sym isym; |
2319 |
|
|
2320 |
|
/* Get the new reloc address. */ |
2321 |
|
raddr = irel->r_offset; |
2322 |
|
if ((raddr >= (addr + count) && raddr < toaddr)) |
2323 |
|
irel->r_offset -= count; |
2324 |
|
|
2325 |
|
if (raddr >= addr && raddr < addr + count) |
2326 |
|
{ |
2327 |
|
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), |
2328 |
|
(int) R_V850_NONE); |
2329 |
|
continue; |
2330 |
|
} |
2331 |
|
|
2332 |
|
if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_ALIGN) |
2333 |
|
continue; |
2334 |
|
|
2335 |
|
bfd_elf32_swap_symbol_in (abfd, |
2336 |
|
extsyms + ELF32_R_SYM (irel->r_info), |
2337 |
|
shndx ? shndx + ELF32_R_SYM (irel->r_info) : NULL, |
2338 |
|
& isym); |
2339 |
|
|
2340 |
|
if (isym.st_shndx != sec_shndx) |
2341 |
|
continue; |
2342 |
|
|
2343 |
|
/* Get the value of the symbol referred to by the reloc. */ |
2344 |
|
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) |
2345 |
|
{ |
2346 |
|
symval = isym.st_value; |
2347 |
|
#if (DEBUG_RELAX & 2) |
2348 |
|
{ |
2349 |
|
char * name = bfd_elf_string_from_elf_section |
2350 |
|
(abfd, symtab_hdr->sh_link, isym.st_name); |
2351 |
|
fprintf (stderr, |
2352 |
|
"relax_delete: local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n", |
2353 |
|
sec->name, name, isym.st_name, |
2354 |
|
sec->output_section->vma, sec->output_offset, |
2355 |
|
isym.st_value, irel->r_addend); |
2356 |
|
} |
2357 |
|
#endif |
2358 |
|
} |
2359 |
|
else |
2360 |
|
{ |
2361 |
|
unsigned long indx; |
2362 |
|
struct elf_link_hash_entry * h; |
2363 |
|
|
2364 |
|
/* An external symbol. */ |
2365 |
|
indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; |
2366 |
|
|
2367 |
|
h = elf_sym_hashes (abfd) [indx]; |
2368 |
|
BFD_ASSERT (h != NULL); |
2369 |
|
|
2370 |
|
symval = h->root.u.def.value; |
2371 |
|
#if (DEBUG_RELAX & 2) |
2372 |
|
fprintf (stderr, |
2373 |
|
"relax_delete: defined: sec: %s, name: %s, value: %x + %x + %x addend %x\n", |
2374 |
|
sec->name, h->root.root.string, h->root.u.def.value, |
2375 |
|
sec->output_section->vma, sec->output_offset, irel->r_addend); |
2376 |
|
#endif |
2377 |
|
} |
2378 |
|
|
2379 |
|
paddr = symval + irel->r_addend; |
2380 |
|
|
2381 |
|
if ( (symval >= addr + count && symval < toaddr) |
2382 |
|
&& (paddr < addr + count || paddr >= toaddr)) |
2383 |
|
irel->r_addend += count; |
2384 |
|
else if ( (symval < addr + count || symval >= toaddr) |
2385 |
|
&& (paddr >= addr + count && paddr < toaddr)) |
2386 |
|
irel->r_addend -= count; |
2387 |
|
} |
2388 |
|
|
2389 |
|
/* Adjust the local symbols defined in this section. */ |
2390 |
|
esym = extsyms; |
2391 |
|
esymend = esym + symtab_hdr->sh_info; |
2392 |
|
|
2393 |
|
for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL)) |
2394 |
|
{ |
2395 |
|
Elf_Internal_Sym isym; |
2396 |
|
|
2397 |
|
bfd_elf32_swap_symbol_in (abfd, esym, shndx, & isym); |
2398 |
|
|
2399 |
|
if (isym.st_shndx == sec_shndx |
2400 |
|
&& isym.st_value >= addr + count |
2401 |
|
&& isym.st_value < toaddr) |
2402 |
|
{ |
2403 |
|
isym.st_value -= count; |
2404 |
|
|
2405 |
|
if (isym.st_value + isym.st_size >= toaddr) |
2406 |
|
isym.st_size += count; |
2407 |
|
|
2408 |
|
bfd_elf32_swap_symbol_out (abfd, & isym, esym, shndx); |
2409 |
|
} |
2410 |
|
else if (isym.st_shndx == sec_shndx |
2411 |
|
&& isym.st_value < addr + count) |
2412 |
|
{ |
2413 |
|
if (isym.st_value+isym.st_size >= addr + count |
2414 |
|
&& isym.st_value+isym.st_size < toaddr) |
2415 |
|
isym.st_size -= count; |
2416 |
|
|
2417 |
|
if (isym.st_value >= addr |
2418 |
|
&& isym.st_value < addr + count) |
2419 |
|
isym.st_value = addr; |
2420 |
|
|
2421 |
|
bfd_elf32_swap_symbol_out (abfd, & isym, esym, shndx); |
2422 |
|
} |
2423 |
|
} |
2424 |
|
|
2425 |
|
/* Now adjust the global symbols defined in this section. */ |
2426 |
|
esym = extsyms + symtab_hdr->sh_info; |
2427 |
|
esymend = extsyms + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)); |
2428 |
|
|
2429 |
|
for (index = 0; esym < esymend; esym ++, index ++) |
2430 |
|
{ |
2431 |
|
Elf_Internal_Sym isym; |
2432 |
|
|
2433 |
|
bfd_elf32_swap_symbol_in (abfd, esym, shndx, & isym); |
2434 |
|
sym_hash = elf_sym_hashes (abfd) [index]; |
2435 |
|
|
2436 |
|
if (isym.st_shndx == sec_shndx |
2437 |
|
&& ((sym_hash)->root.type == bfd_link_hash_defined |
2438 |
|
|| (sym_hash)->root.type == bfd_link_hash_defweak) |
2439 |
|
&& (sym_hash)->root.u.def.section == sec |
2440 |
|
&& (sym_hash)->root.u.def.value >= addr + count |
2441 |
|
&& (sym_hash)->root.u.def.value < toaddr) |
2442 |
|
{ |
2443 |
|
if ((sym_hash)->root.u.def.value + isym.st_size >= toaddr) |
2444 |
|
{ |
2445 |
|
isym.st_size += count; |
2446 |
|
bfd_elf32_swap_symbol_out (abfd, & isym, esym, shndx); |
2447 |
|
} |
2448 |
|
|
2449 |
|
(sym_hash)->root.u.def.value -= count; |
2450 |
|
} |
2451 |
|
else if (isym.st_shndx == sec_shndx |
2452 |
|
&& ((sym_hash)->root.type == bfd_link_hash_defined |
2453 |
|
|| (sym_hash)->root.type == bfd_link_hash_defweak) |
2454 |
|
&& (sym_hash)->root.u.def.section == sec |
2455 |
|
&& (sym_hash)->root.u.def.value < addr + count) |
2456 |
|
{ |
2457 |
|
if ((sym_hash)->root.u.def.value+isym.st_size >= addr + count |
2458 |
|
&& (sym_hash)->root.u.def.value+isym.st_size < toaddr) |
2459 |
|
isym.st_size -= count; |
2460 |
|
|
2461 |
|
if ((sym_hash)->root.u.def.value >= addr |
2462 |
|
&& (sym_hash)->root.u.def.value < addr + count) |
2463 |
|
(sym_hash)->root.u.def.value = addr; |
2464 |
|
|
2465 |
|
bfd_elf32_swap_symbol_out (abfd, & isym, esym, shndx); |
2466 |
|
} |
2467 |
|
|
2468 |
|
if (shndx) |
2469 |
|
++ shndx; |
2470 |
|
} |
2471 |
|
|
2472 |
|
return TRUE; |
2473 |
} |
} |
2474 |
|
|
2475 |
|
#define NOP_OPCODE (0x0000) |
2476 |
|
#define MOVHI 0x0640 /* 4byte */ |
2477 |
|
#define MOVHI_MASK 0x07e0 |
2478 |
|
#define MOVHI_R1(insn) ((insn) & 0x1f) /* 4byte */ |
2479 |
|
#define MOVHI_R2(insn) ((insn) >> 11) |
2480 |
|
#define MOVEA 0x0620 /* 2byte */ |
2481 |
|
#define MOVEA_MASK 0x07e0 |
2482 |
|
#define MOVEA_R1(insn) ((insn) & 0x1f) |
2483 |
|
#define MOVEA_R2(insn) ((insn) >> 11) |
2484 |
|
#define JARL_4 0x00040780 /* 4byte */ |
2485 |
|
#define JARL_4_MASK 0xFFFF07FF |
2486 |
|
#define JARL_R2(insn) (int)(((insn) & (~JARL_4_MASK)) >> 11) |
2487 |
|
#define ADD_I 0x0240 /* 2byte */ |
2488 |
|
#define ADD_I_MASK 0x07e0 |
2489 |
|
#define ADD_I5(insn) ((((insn) & 0x001f) << 11) >> 11) /* 2byte */ |
2490 |
|
#define ADD_R2(insn) ((insn) >> 11) |
2491 |
|
#define JMP_R 0x0060 /* 2byte */ |
2492 |
|
#define JMP_R_MASK 0xFFE0 |
2493 |
|
#define JMP_R1(insn) ((insn) & 0x1f) |
2494 |
|
|
2495 |
|
static bfd_boolean |
2496 |
|
v850_elf_relax_section (abfd, sec, link_info, again) |
2497 |
|
bfd *abfd; |
2498 |
|
asection *sec; |
2499 |
|
struct bfd_link_info *link_info; |
2500 |
|
bfd_boolean *again; |
2501 |
|
{ |
2502 |
|
Elf_Internal_Shdr *symtab_hdr; |
2503 |
|
Elf_Internal_Rela *internal_relocs; |
2504 |
|
Elf_Internal_Rela *irel; |
2505 |
|
Elf_Internal_Rela *irelend; |
2506 |
|
Elf_Internal_Rela *irelalign = NULL; |
2507 |
|
Elf_Internal_Sym *isymbuf = NULL; |
2508 |
|
bfd_byte *contents = NULL; |
2509 |
|
bfd_vma addr = 0; |
2510 |
|
bfd_vma toaddr; |
2511 |
|
int align_pad_size = 0; |
2512 |
|
bfd_boolean result = TRUE; |
2513 |
|
|
2514 |
|
*again = FALSE; |
2515 |
|
|
2516 |
|
if (link_info->relocatable |
2517 |
|
|| (sec->flags & SEC_RELOC) == 0 |
2518 |
|
|| sec->reloc_count == 0) |
2519 |
|
return TRUE; |
2520 |
|
|
2521 |
|
symtab_hdr = & elf_tdata (abfd)->symtab_hdr; |
2522 |
|
|
2523 |
|
internal_relocs = (_bfd_elf_link_read_relocs |
2524 |
|
(abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, |
2525 |
|
link_info->keep_memory)); |
2526 |
|
if (internal_relocs == NULL) |
2527 |
|
goto error_return; |
2528 |
|
|
2529 |
|
irelend = internal_relocs + sec->reloc_count; |
2530 |
|
|
2531 |
|
while (addr < sec->size) |
2532 |
|
{ |
2533 |
|
toaddr = sec->size; |
2534 |
|
|
2535 |
|
for (irel = internal_relocs; irel < irelend; irel ++) |
2536 |
|
if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_ALIGN |
2537 |
|
&& irel->r_offset > addr |
2538 |
|
&& irel->r_offset < toaddr) |
2539 |
|
toaddr = irel->r_offset; |
2540 |
|
|
2541 |
|
#ifdef DEBUG_RELAX |
2542 |
|
fprintf (stderr, "relax region 0x%x to 0x%x align pad %d\n", |
2543 |
|
addr, toaddr, align_pad_size); |
2544 |
|
#endif |
2545 |
|
if (irelalign) |
2546 |
|
{ |
2547 |
|
bfd_vma alignto; |
2548 |
|
bfd_vma alignmoveto; |
2549 |
|
|
2550 |
|
alignmoveto = BFD_ALIGN (addr - align_pad_size, 1 << irelalign->r_addend); |
2551 |
|
alignto = BFD_ALIGN (addr, 1 << irelalign->r_addend); |
2552 |
|
|
2553 |
|
if (alignmoveto < alignto) |
2554 |
|
{ |
2555 |
|
unsigned int i; |
2556 |
|
|
2557 |
|
align_pad_size = alignto - alignmoveto; |
2558 |
|
#ifdef DEBUG_RELAX |
2559 |
|
fprintf (stderr, "relax move region 0x%x to 0x%x delete size 0x%x\n", |
2560 |
|
alignmoveto, toaddr, align_pad_size); |
2561 |
|
#endif |
2562 |
|
if (!v850_elf_relax_delete_bytes (abfd, sec, alignmoveto, |
2563 |
|
toaddr, align_pad_size)) |
2564 |
|
goto error_return; |
2565 |
|
|
2566 |
|
for (i = BFD_ALIGN (toaddr - align_pad_size, 1); |
2567 |
|
(i + 1) < toaddr; i += 2) |
2568 |
|
bfd_put_16 (abfd, NOP_OPCODE, contents + i); |
2569 |
|
|
2570 |
|
addr = alignmoveto; |
2571 |
|
} |
2572 |
|
else |
2573 |
|
align_pad_size = 0; |
2574 |
|
} |
2575 |
|
|
2576 |
|
for (irel = internal_relocs; irel < irelend; irel++) |
2577 |
|
{ |
2578 |
|
bfd_vma laddr; |
2579 |
|
bfd_vma addend; |
2580 |
|
bfd_vma symval; |
2581 |
|
int insn[5]; |
2582 |
|
int no_match = -1; |
2583 |
|
Elf_Internal_Rela *hi_irelfn; |
2584 |
|
Elf_Internal_Rela *lo_irelfn; |
2585 |
|
Elf_Internal_Rela *irelcall; |
2586 |
|
bfd_signed_vma foff; |
2587 |
|
|
2588 |
|
if (! (irel->r_offset >= addr && irel->r_offset < toaddr |
2589 |
|
&& (ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGCALL |
2590 |
|
|| ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGJUMP))) |
2591 |
|
continue; |
2592 |
|
|
2593 |
|
#ifdef DEBUG_RELAX |
2594 |
|
fprintf (stderr, "relax check r_info 0x%x r_offset 0x%x r_addend 0x%x\n", |
2595 |
|
irel->r_info, |
2596 |
|
irel->r_offset, |
2597 |
|
irel->r_addend ); |
2598 |
|
#endif |
2599 |
|
|
2600 |
|
/* Get the section contents. */ |
2601 |
|
if (contents == NULL) |
2602 |
|
{ |
2603 |
|
if (elf_section_data (sec)->this_hdr.contents != NULL) |
2604 |
|
contents = elf_section_data (sec)->this_hdr.contents; |
2605 |
|
else |
2606 |
|
{ |
2607 |
|
if (!bfd_malloc_and_get_section (abfd, sec, &contents)) |
2608 |
|
goto error_return; |
2609 |
|
} |
2610 |
|
} |
2611 |
|
|
2612 |
|
/* Read this BFD's local symbols if we haven't done so already. */ |
2613 |
|
if (isymbuf == NULL && symtab_hdr->sh_info != 0) |
2614 |
|
{ |
2615 |
|
isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; |
2616 |
|
if (isymbuf == NULL) |
2617 |
|
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, |
2618 |
|
symtab_hdr->sh_info, 0, |
2619 |
|
NULL, NULL, NULL); |
2620 |
|
if (isymbuf == NULL) |
2621 |
|
goto error_return; |
2622 |
|
} |
2623 |
|
|
2624 |
|
laddr = irel->r_offset; |
2625 |
|
|
2626 |
|
if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGCALL) |
2627 |
|
{ |
2628 |
|
/* Check code for -mlong-calls output. */ |
2629 |
|
if (laddr + 16 <= (bfd_vma) sec->size) |
2630 |
|
{ |
2631 |
|
insn[0] = bfd_get_16 (abfd, contents + laddr); |
2632 |
|
insn[1] = bfd_get_16 (abfd, contents + laddr + 4); |
2633 |
|
insn[2] = bfd_get_32 (abfd, contents + laddr + 8); |
2634 |
|
insn[3] = bfd_get_16 (abfd, contents + laddr + 12); |
2635 |
|
insn[4] = bfd_get_16 (abfd, contents + laddr + 14); |
2636 |
|
|
2637 |
|
if ((insn[0] & MOVHI_MASK) != MOVHI |
2638 |
|
|| MOVHI_R1 (insn[0]) != 0) |
2639 |
|
no_match = 0; |
2640 |
|
|
2641 |
|
if (no_match < 0 |
2642 |
|
&& ((insn[1] & MOVEA_MASK) != MOVEA |
2643 |
|
|| MOVHI_R2 (insn[0]) != MOVEA_R1 (insn[1]))) |
2644 |
|
no_match = 1; |
2645 |
|
|
2646 |
|
if (no_match < 0 |
2647 |
|
&& (insn[2] & JARL_4_MASK) != JARL_4) |
2648 |
|
no_match = 2; |
2649 |
|
|
2650 |
|
if (no_match < 0 |
2651 |
|
&& ((insn[3] & ADD_I_MASK) != ADD_I |
2652 |
|
|| ADD_I5 (insn[3]) != 4 |
2653 |
|
|| JARL_R2 (insn[2]) != ADD_R2 (insn[3]))) |
2654 |
|
no_match = 3; |
2655 |
|
|
2656 |
|
if (no_match < 0 |
2657 |
|
&& ((insn[4] & JMP_R_MASK) != JMP_R |
2658 |
|
|| MOVEA_R2 (insn[1]) != JMP_R1 (insn[4]))) |
2659 |
|
no_match = 4; |
2660 |
|
} |
2661 |
|
else |
2662 |
|
{ |
2663 |
|
((*_bfd_error_handler) |
2664 |
|
("%s: 0x%lx: warning: R_V850_LONGCALL points to unrecognized insns", |
2665 |
|
bfd_get_filename (abfd), (unsigned long) irel->r_offset)); |
2666 |
|
|
2667 |
|
continue; |
2668 |
|
} |
2669 |
|
|
2670 |
|
if (no_match >= 0) |
2671 |
|
{ |
2672 |
|
((*_bfd_error_handler) |
2673 |
|
("%s: 0x%lx: warning: R_V850_LONGCALL points to unrecognized insn 0x%x", |
2674 |
|
bfd_get_filename (abfd), (unsigned long) irel->r_offset+no_match, insn[no_match])); |
2675 |
|
|
2676 |
|
continue; |
2677 |
|
} |
2678 |
|
|
2679 |
|
/* Get the reloc for the address from which the register is |
2680 |
|
being loaded. This reloc will tell us which function is |
2681 |
|
actually being called. */ |
2682 |
|
for (hi_irelfn = internal_relocs; hi_irelfn < irelend; hi_irelfn ++) |
2683 |
|
if (hi_irelfn->r_offset == laddr + 2 |
2684 |
|
&& ELF32_R_TYPE (hi_irelfn->r_info) |
2685 |
|
== (int) R_V850_HI16_S) |
2686 |
|
break; |
2687 |
|
|
2688 |
|
for (lo_irelfn = internal_relocs; lo_irelfn < irelend; lo_irelfn ++) |
2689 |
|
if (lo_irelfn->r_offset == laddr + 6 |
2690 |
|
&& ELF32_R_TYPE (lo_irelfn->r_info) |
2691 |
|
== (int) R_V850_LO16) |
2692 |
|
break; |
2693 |
|
|
2694 |
|
for (irelcall = internal_relocs; irelcall < irelend; irelcall ++) |
2695 |
|
if (irelcall->r_offset == laddr + 8 |
2696 |
|
&& ELF32_R_TYPE (irelcall->r_info) |
2697 |
|
== (int) R_V850_22_PCREL) |
2698 |
|
break; |
2699 |
|
|
2700 |
|
if ( hi_irelfn == irelend |
2701 |
|
|| lo_irelfn == irelend |
2702 |
|
|| irelcall == irelend) |
2703 |
|
{ |
2704 |
|
((*_bfd_error_handler) |
2705 |
|
("%s: 0x%lx: warning: R_V850_LONGCALL points to unrecognized reloc", |
2706 |
|
bfd_get_filename (abfd), (unsigned long) irel->r_offset )); |
2707 |
|
|
2708 |
|
continue; |
2709 |
|
} |
2710 |
|
|
2711 |
|
if (ELF32_R_SYM (irelcall->r_info) < symtab_hdr->sh_info) |
2712 |
|
{ |
2713 |
|
Elf_Internal_Sym * isym; |
2714 |
|
|
2715 |
|
/* A local symbol. */ |
2716 |
|
isym = isymbuf + ELF32_R_SYM (irelcall->r_info); |
2717 |
|
|
2718 |
|
symval = isym->st_value; |
2719 |
|
} |
2720 |
|
else |
2721 |
|
{ |
2722 |
|
unsigned long indx; |
2723 |
|
struct elf_link_hash_entry * h; |
2724 |
|
|
2725 |
|
/* An external symbol. */ |
2726 |
|
indx = ELF32_R_SYM (irelcall->r_info) - symtab_hdr->sh_info; |
2727 |
|
h = elf_sym_hashes (abfd)[indx]; |
2728 |
|
BFD_ASSERT (h != NULL); |
2729 |
|
|
2730 |
|
if ( h->root.type != bfd_link_hash_defined |
2731 |
|
&& h->root.type != bfd_link_hash_defweak) |
2732 |
|
/* This appears to be a reference to an undefined |
2733 |
|
symbol. Just ignore it--it will be caught by the |
2734 |
|
regular reloc processing. */ |
2735 |
|
continue; |
2736 |
|
|
2737 |
|
symval = h->root.u.def.value; |
2738 |
|
} |
2739 |
|
|
2740 |
|
if (symval + irelcall->r_addend != irelcall->r_offset + 4) |
2741 |
|
{ |
2742 |
|
((*_bfd_error_handler) |
2743 |
|
("%s: 0x%lx: warning: R_V850_LONGCALL points to unrecognized reloc 0x%lx", |
2744 |
|
bfd_get_filename (abfd), (unsigned long) irel->r_offset, irelcall->r_offset )); |
2745 |
|
|
2746 |
|
continue; |
2747 |
|
} |
2748 |
|
|
2749 |
|
/* Get the value of the symbol referred to by the reloc. */ |
2750 |
|
if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info) |
2751 |
|
{ |
2752 |
|
Elf_Internal_Sym *isym; |
2753 |
|
asection *sym_sec; |
2754 |
|
|
2755 |
|
/* A local symbol. */ |
2756 |
|
isym = isymbuf + ELF32_R_SYM (hi_irelfn->r_info); |
2757 |
|
|
2758 |
|
if (isym->st_shndx == SHN_UNDEF) |
2759 |
|
sym_sec = bfd_und_section_ptr; |
2760 |
|
else if (isym->st_shndx == SHN_ABS) |
2761 |
|
sym_sec = bfd_abs_section_ptr; |
2762 |
|
else if (isym->st_shndx == SHN_COMMON) |
2763 |
|
sym_sec = bfd_com_section_ptr; |
2764 |
|
else |
2765 |
|
sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); |
2766 |
|
symval = (isym->st_value |
2767 |
|
+ sym_sec->output_section->vma |
2768 |
|
+ sym_sec->output_offset); |
2769 |
|
} |
2770 |
|
else |
2771 |
|
{ |
2772 |
|
unsigned long indx; |
2773 |
|
struct elf_link_hash_entry *h; |
2774 |
|
|
2775 |
|
/* An external symbol. */ |
2776 |
|
indx = ELF32_R_SYM (hi_irelfn->r_info) - symtab_hdr->sh_info; |
2777 |
|
h = elf_sym_hashes (abfd)[indx]; |
2778 |
|
BFD_ASSERT (h != NULL); |
2779 |
|
|
2780 |
|
if ( h->root.type != bfd_link_hash_defined |
2781 |
|
&& h->root.type != bfd_link_hash_defweak) |
2782 |
|
/* This appears to be a reference to an undefined |
2783 |
|
symbol. Just ignore it--it will be caught by the |
2784 |
|
regular reloc processing. */ |
2785 |
|
continue; |
2786 |
|
|
2787 |
|
symval = (h->root.u.def.value |
2788 |
|
+ h->root.u.def.section->output_section->vma |
2789 |
|
+ h->root.u.def.section->output_offset); |
2790 |
|
} |
2791 |
|
|
2792 |
|
addend = irel->r_addend; |
2793 |
|
|
2794 |
|
foff = (symval + addend |
2795 |
|
- (irel->r_offset |
2796 |
|
+ sec->output_section->vma |
2797 |
|
+ sec->output_offset |
2798 |
|
+ 4)); |
2799 |
|
#ifdef DEBUG_RELAX |
2800 |
|
fprintf (stderr, "relax longcall r_offset 0x%x ptr 0x%x symbol 0x%x addend 0x%x distance 0x%x\n", |
2801 |
|
irel->r_offset, |
2802 |
|
(irel->r_offset |
2803 |
|
+ sec->output_section->vma |
2804 |
|
+ sec->output_offset), |
2805 |
|
symval, addend, foff); |
2806 |
|
#endif |
2807 |
|
|
2808 |
|
if (foff < -0x100000 || foff >= 0x100000) |
2809 |
|
/* After all that work, we can't shorten this function call. */ |
2810 |
|
continue; |
2811 |
|
|
2812 |
|
/* For simplicity of coding, we are going to modify the section |
2813 |
|
contents, the section relocs, and the BFD symbol table. We |
2814 |
|
must tell the rest of the code not to free up this |
2815 |
|
information. It would be possible to instead create a table |
2816 |
|
of changes which have to be made, as is done in coff-mips.c; |
2817 |
|
that would be more work, but would require less memory when |
2818 |
|
the linker is run. */ |
2819 |
|
elf_section_data (sec)->relocs = internal_relocs; |
2820 |
|
elf_section_data (sec)->this_hdr.contents = contents; |
2821 |
|
symtab_hdr->contents = (bfd_byte *) isymbuf; |
2822 |
|
|
2823 |
|
/* Replace the long call with a jarl. */ |
2824 |
|
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_22_PCREL); |
2825 |
|
|
2826 |
|
addend = 0; |
2827 |
|
|
2828 |
|
if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info) |
2829 |
|
/* If this needs to be changed because of future relaxing, |
2830 |
|
it will be handled here like other internal IND12W |
2831 |
|
relocs. */ |
2832 |
|
bfd_put_32 (abfd, |
2833 |
|
0x00000780 | (JARL_R2 (insn[2])<<11) | ((addend << 16) & 0xffff) | ((addend >> 16) & 0xf), |
2834 |
|
contents + irel->r_offset); |
2835 |
|
else |
2836 |
|
/* We can't fully resolve this yet, because the external |
2837 |
|
symbol value may be changed by future relaxing. |
2838 |
|
We let the final link phase handle it. */ |
2839 |
|
bfd_put_32 (abfd, 0x00000780 | (JARL_R2 (insn[2])<<11), |
2840 |
|
contents + irel->r_offset); |
2841 |
|
|
2842 |
|
hi_irelfn->r_info = |
2843 |
|
ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_NONE); |
2844 |
|
lo_irelfn->r_info = |
2845 |
|
ELF32_R_INFO (ELF32_R_SYM (lo_irelfn->r_info), R_V850_NONE); |
2846 |
|
irelcall->r_info = |
2847 |
|
ELF32_R_INFO (ELF32_R_SYM (irelcall->r_info), R_V850_NONE); |
2848 |
|
|
2849 |
|
if (! v850_elf_relax_delete_bytes (abfd, sec, |
2850 |
|
irel->r_offset + 4, toaddr, 12)) |
2851 |
|
goto error_return; |
2852 |
|
|
2853 |
|
align_pad_size += 12; |
2854 |
|
} |
2855 |
|
else if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGJUMP) |
2856 |
|
{ |
2857 |
|
/* Check code for -mlong-jumps output. */ |
2858 |
|
if (laddr + 10 <= (bfd_vma) sec->size) |
2859 |
|
{ |
2860 |
|
insn[0] = bfd_get_16 (abfd, contents + laddr); |
2861 |
|
insn[1] = bfd_get_16 (abfd, contents + laddr + 4); |
2862 |
|
insn[2] = bfd_get_16 (abfd, contents + laddr + 8); |
2863 |
|
|
2864 |
|
if ((insn[0] & MOVHI_MASK) != MOVHI |
2865 |
|
|| MOVHI_R1 (insn[0]) != 0) |
2866 |
|
no_match = 0; |
2867 |
|
|
2868 |
|
if (no_match < 0 |
2869 |
|
&& ((insn[1] & MOVEA_MASK) != MOVEA |
2870 |
|
|| MOVHI_R2 (insn[0]) != MOVEA_R1 (insn[1]))) |
2871 |
|
no_match = 1; |
2872 |
|
|
2873 |
|
if (no_match < 0 |
2874 |
|
&& ((insn[2] & JMP_R_MASK) != JMP_R |
2875 |
|
|| MOVEA_R2 (insn[1]) != JMP_R1 (insn[2]))) |
2876 |
|
no_match = 4; |
2877 |
|
} |
2878 |
|
else |
2879 |
|
{ |
2880 |
|
((*_bfd_error_handler) |
2881 |
|
("%s: 0x%lx: warning: R_V850_LONGJUMP points to unrecognized insns", |
2882 |
|
bfd_get_filename (abfd), (unsigned long) irel->r_offset)); |
2883 |
|
|
2884 |
|
continue; |
2885 |
|
} |
2886 |
|
|
2887 |
|
if (no_match >= 0) |
2888 |
|
{ |
2889 |
|
((*_bfd_error_handler) |
2890 |
|
("%s: 0x%lx: warning: R_V850_LONGJUMP points to unrecognized insn 0x%x", |
2891 |
|
bfd_get_filename (abfd), (unsigned long) irel->r_offset+no_match, insn[no_match])); |
2892 |
|
|
2893 |
|
continue; |
2894 |
|
} |
2895 |
|
|
2896 |
|
/* Get the reloc for the address from which the register is |
2897 |
|
being loaded. This reloc will tell us which function is |
2898 |
|
actually being called. */ |
2899 |
|
for (hi_irelfn = internal_relocs; hi_irelfn < irelend; hi_irelfn ++) |
2900 |
|
if (hi_irelfn->r_offset == laddr + 2 |
2901 |
|
&& ELF32_R_TYPE (hi_irelfn->r_info) == (int) R_V850_HI16_S) |
2902 |
|
break; |
2903 |
|
|
2904 |
|
for (lo_irelfn = internal_relocs; lo_irelfn < irelend; lo_irelfn ++) |
2905 |
|
if (lo_irelfn->r_offset == laddr + 6 |
2906 |
|
&& ELF32_R_TYPE (lo_irelfn->r_info) == (int) R_V850_LO16) |
2907 |
|
break; |
2908 |
|
|
2909 |
|
if ( hi_irelfn == irelend |
2910 |
|
|| lo_irelfn == irelend) |
2911 |
|
{ |
2912 |
|
((*_bfd_error_handler) |
2913 |
|
("%s: 0x%lx: warning: R_V850_LONGJUMP points to unrecognized reloc", |
2914 |
|
bfd_get_filename (abfd), (unsigned long) irel->r_offset )); |
2915 |
|
|
2916 |
|
continue; |
2917 |
|
} |
2918 |
|
|
2919 |
|
/* Get the value of the symbol referred to by the reloc. */ |
2920 |
|
if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info) |
2921 |
|
{ |
2922 |
|
Elf_Internal_Sym * isym; |
2923 |
|
asection * sym_sec; |
2924 |
|
|
2925 |
|
/* A local symbol. */ |
2926 |
|
isym = isymbuf + ELF32_R_SYM (hi_irelfn->r_info); |
2927 |
|
|
2928 |
|
if (isym->st_shndx == SHN_UNDEF) |
2929 |
|
sym_sec = bfd_und_section_ptr; |
2930 |
|
else if (isym->st_shndx == SHN_ABS) |
2931 |
|
sym_sec = bfd_abs_section_ptr; |
2932 |
|
else if (isym->st_shndx == SHN_COMMON) |
2933 |
|
sym_sec = bfd_com_section_ptr; |
2934 |
|
else |
2935 |
|
sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); |
2936 |
|
symval = (isym->st_value |
2937 |
|
+ sym_sec->output_section->vma |
2938 |
|
+ sym_sec->output_offset); |
2939 |
|
#ifdef DEBUG_RELAX |
2940 |
|
{ |
2941 |
|
char * name = bfd_elf_string_from_elf_section |
2942 |
|
(abfd, symtab_hdr->sh_link, isym->st_name); |
2943 |
|
|
2944 |
|
fprintf (stderr, "relax long jump local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n", |
2945 |
|
sym_sec->name, name, isym->st_name, |
2946 |
|
sym_sec->output_section->vma, |
2947 |
|
sym_sec->output_offset, |
2948 |
|
isym->st_value, irel->r_addend); |
2949 |
|
} |
2950 |
|
#endif |
2951 |
|
} |
2952 |
|
else |
2953 |
|
{ |
2954 |
|
unsigned long indx; |
2955 |
|
struct elf_link_hash_entry * h; |
2956 |
|
|
2957 |
|
/* An external symbol. */ |
2958 |
|
indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; |
2959 |
|
h = elf_sym_hashes (abfd)[indx]; |
2960 |
|
BFD_ASSERT (h != NULL); |
2961 |
|
|
2962 |
|
if ( h->root.type != bfd_link_hash_defined |
2963 |
|
&& h->root.type != bfd_link_hash_defweak) |
2964 |
|
/* This appears to be a reference to an undefined |
2965 |
|
symbol. Just ignore it--it will be caught by the |
2966 |
|
regular reloc processing. */ |
2967 |
|
continue; |
2968 |
|
|
2969 |
|
symval = (h->root.u.def.value |
2970 |
|
+ h->root.u.def.section->output_section->vma |
2971 |
|
+ h->root.u.def.section->output_offset); |
2972 |
|
#ifdef DEBUG_RELAX |
2973 |
|
fprintf (stderr, |
2974 |
|
"relax longjump defined: sec: %s, name: %s, value: %x + %x + %x addend %x\n", |
2975 |
|
sec->name, h->root.root.string, h->root.u.def.value, |
2976 |
|
sec->output_section->vma, sec->output_offset, irel->r_addend); |
2977 |
|
#endif |
2978 |
|
} |
2979 |
|
|
2980 |
|
addend = irel->r_addend; |
2981 |
|
|
2982 |
|
foff = (symval + addend |
2983 |
|
- (irel->r_offset |
2984 |
|
+ sec->output_section->vma |
2985 |
|
+ sec->output_offset |
2986 |
|
+ 4)); |
2987 |
|
#ifdef DEBUG_RELAX |
2988 |
|
fprintf (stderr, "relax longjump r_offset 0x%x ptr 0x%x symbol 0x%x addend 0x%x distance 0x%x\n", |
2989 |
|
irel->r_offset, |
2990 |
|
(irel->r_offset |
2991 |
|
+ sec->output_section->vma |
2992 |
|
+ sec->output_offset), |
2993 |
|
symval, addend, foff); |
2994 |
|
#endif |
2995 |
|
if (foff < -0x100000 || foff >= 0x100000) |
2996 |
|
/* After all that work, we can't shorten this function call. */ |
2997 |
|
continue; |
2998 |
|
|
2999 |
|
/* For simplicity of coding, we are going to modify the section |
3000 |
|
contents, the section relocs, and the BFD symbol table. We |
3001 |
|
must tell the rest of the code not to free up this |
3002 |
|
information. It would be possible to instead create a table |
3003 |
|
of changes which have to be made, as is done in coff-mips.c; |
3004 |
|
that would be more work, but would require less memory when |
3005 |
|
the linker is run. */ |
3006 |
|
elf_section_data (sec)->relocs = internal_relocs; |
3007 |
|
elf_section_data (sec)->this_hdr.contents = contents; |
3008 |
|
symtab_hdr->contents = (bfd_byte *) isymbuf; |
3009 |
|
|
3010 |
|
if (foff < -0x100 || foff >= 0x100) |
3011 |
|
{ |
3012 |
|
/* Replace the long jump with a jr. */ |
3013 |
|
|
3014 |
|
irel->r_info = |
3015 |
|
ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_22_PCREL); |
3016 |
|
|
3017 |
|
irel->r_addend = addend; |
3018 |
|
addend = 0; |
3019 |
|
|
3020 |
|
if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info) |
3021 |
|
/* If this needs to be changed because of future relaxing, |
3022 |
|
it will be handled here like other internal IND12W |
3023 |
|
relocs. */ |
3024 |
|
bfd_put_32 (abfd, |
3025 |
|
0x00000780 | ((addend << 15) & 0xffff0000) | ((addend >> 17) & 0xf), |
3026 |
|
contents + irel->r_offset); |
3027 |
|
else |
3028 |
|
/* We can't fully resolve this yet, because the external |
3029 |
|
symbol value may be changed by future relaxing. |
3030 |
|
We let the final link phase handle it. */ |
3031 |
|
bfd_put_32 (abfd, 0x00000780, contents + irel->r_offset); |
3032 |
|
|
3033 |
|
hi_irelfn->r_info = |
3034 |
|
ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_NONE); |
3035 |
|
lo_irelfn->r_info = |
3036 |
|
ELF32_R_INFO (ELF32_R_SYM (lo_irelfn->r_info), R_V850_NONE); |
3037 |
|
if (!v850_elf_relax_delete_bytes (abfd, sec, |
3038 |
|
irel->r_offset + 4, toaddr, 6)) |
3039 |
|
goto error_return; |
3040 |
|
|
3041 |
|
align_pad_size += 6; |
3042 |
|
} |
3043 |
|
else |
3044 |
|
{ |
3045 |
|
/* Replace the long jump with a br. */ |
3046 |
|
|
3047 |
|
irel->r_info = |
3048 |
|
ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_9_PCREL); |
3049 |
|
|
3050 |
|
irel->r_addend = addend; |
3051 |
|
addend = 0; |
3052 |
|
|
3053 |
|
if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info) |
3054 |
|
/* If this needs to be changed because of future relaxing, |
3055 |
|
it will be handled here like other internal IND12W |
3056 |
|
relocs. */ |
3057 |
|
bfd_put_16 (abfd, |
3058 |
|
0x0585 | ((addend << 10) & 0xf800) | ((addend << 3) & 0x0070), |
3059 |
|
contents + irel->r_offset); |
3060 |
|
else |
3061 |
|
/* We can't fully resolve this yet, because the external |
3062 |
|
symbol value may be changed by future relaxing. |
3063 |
|
We let the final link phase handle it. */ |
3064 |
|
bfd_put_16 (abfd, 0x0585, contents + irel->r_offset); |
3065 |
|
|
3066 |
|
hi_irelfn->r_info = |
3067 |
|
ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_NONE); |
3068 |
|
lo_irelfn->r_info = |
3069 |
|
ELF32_R_INFO (ELF32_R_SYM (lo_irelfn->r_info), R_V850_NONE); |
3070 |
|
if (!v850_elf_relax_delete_bytes (abfd, sec, |
3071 |
|
irel->r_offset + 2, toaddr, 8)) |
3072 |
|
goto error_return; |
3073 |
|
|
3074 |
|
align_pad_size += 8; |
3075 |
|
} |
3076 |
|
} |
3077 |
|
} |
3078 |
|
|
3079 |
|
irelalign = NULL; |
3080 |
|
for (irel = internal_relocs; irel < irelend; irel++) |
3081 |
|
{ |
3082 |
|
if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_ALIGN |
3083 |
|
&& irel->r_offset == toaddr) |
3084 |
|
{ |
3085 |
|
irel->r_offset -= align_pad_size; |
3086 |
|
|
3087 |
|
if (irelalign == NULL || irelalign->r_addend > irel->r_addend) |
3088 |
|
irelalign = irel; |
3089 |
|
} |
3090 |
|
} |
3091 |
|
|
3092 |
|
addr = toaddr; |
3093 |
|
} |
3094 |
|
|
3095 |
|
if (!irelalign) |
3096 |
|
{ |
3097 |
|
#ifdef DEBUG_RELAX |
3098 |
|
fprintf (stderr, "relax pad %d shorten %d -> %d\n", |
3099 |
|
align_pad_size, |
3100 |
|
sec->size, |
3101 |
|
sec->size - align_pad_size); |
3102 |
|
#endif |
3103 |
|
sec->size -= align_pad_size; |
3104 |
|
} |
3105 |
|
|
3106 |
|
finish: |
3107 |
|
if (internal_relocs != NULL |
3108 |
|
&& elf_section_data (sec)->relocs != internal_relocs) |
3109 |
|
free (internal_relocs); |
3110 |
|
|
3111 |
|
if (contents != NULL |
3112 |
|
&& elf_section_data (sec)->this_hdr.contents != (unsigned char *) contents) |
3113 |
|
free (contents); |
3114 |
|
|
3115 |
|
if (isymbuf != NULL |
3116 |
|
&& symtab_hdr->contents != (bfd_byte *) isymbuf) |
3117 |
|
free (isymbuf); |
3118 |
|
|
3119 |
|
return result; |
3120 |
|
|
3121 |
|
error_return: |
3122 |
|
result = FALSE; |
3123 |
|
goto finish; |
3124 |
|
} |
3125 |
|
|
3126 |
|
static struct bfd_elf_special_section const v850_elf_special_sections[]= |
3127 |
|
{ |
3128 |
|
{ ".sdata", 6, -2, SHT_PROGBITS, (SHF_ALLOC + SHF_WRITE |
3129 |
|
+ SHF_V850_GPREL) }, |
3130 |
|
{ ".rosdata", 8, -2, SHT_PROGBITS, (SHF_ALLOC |
3131 |
|
+ SHF_V850_GPREL) }, |
3132 |
|
{ ".sbss", 5, -2, SHT_NOBITS, (SHF_ALLOC + SHF_WRITE |
3133 |
|
+ SHF_V850_GPREL) }, |
3134 |
|
{ ".scommon", 8, -2, SHT_V850_SCOMMON, (SHF_ALLOC + SHF_WRITE |
3135 |
|
+ SHF_V850_GPREL) }, |
3136 |
|
{ ".tdata", 6, -2, SHT_PROGBITS, (SHF_ALLOC + SHF_WRITE |
3137 |
|
+ SHF_V850_EPREL) }, |
3138 |
|
{ ".tbss", 5, -2, SHT_NOBITS, (SHF_ALLOC + SHF_WRITE |
3139 |
|
+ SHF_V850_EPREL) }, |
3140 |
|
{ ".tcommon", 8, -2, SHT_V850_TCOMMON, (SHF_ALLOC + SHF_WRITE |
3141 |
|
+ SHF_V850_R0REL) }, |
3142 |
|
{ ".zdata", 6, -2, SHT_PROGBITS, (SHF_ALLOC + SHF_WRITE |
3143 |
|
+ SHF_V850_R0REL) }, |
3144 |
|
{ ".rozdata", 8, -2, SHT_PROGBITS, (SHF_ALLOC |
3145 |
|
+ SHF_V850_R0REL) }, |
3146 |
|
{ ".zbss", 5, -2, SHT_NOBITS, (SHF_ALLOC + SHF_WRITE |
3147 |
|
+ SHF_V850_R0REL) }, |
3148 |
|
{ ".zcommon", 8, -2, SHT_V850_ZCOMMON, (SHF_ALLOC + SHF_WRITE |
3149 |
|
+ SHF_V850_R0REL) }, |
3150 |
|
{ ".call_table_data", 16, 0, SHT_PROGBITS, (SHF_ALLOC |
3151 |
|
+ SHF_WRITE) }, |
3152 |
|
{ ".call_table_text", 16, 0, SHT_PROGBITS, (SHF_ALLOC + SHF_WRITE |
3153 |
|
+ SHF_EXECINSTR) }, |
3154 |
|
{ NULL, 0, 0, 0, 0 } |
3155 |
|
}; |
3156 |
|
|
3157 |
#define TARGET_LITTLE_SYM bfd_elf32_v850_vec |
#define TARGET_LITTLE_SYM bfd_elf32_v850_vec |
3158 |
#define TARGET_LITTLE_NAME "elf32-v850" |
#define TARGET_LITTLE_NAME "elf32-v850" |
3176 |
#define elf_backend_fake_sections v850_elf_fake_sections |
#define elf_backend_fake_sections v850_elf_fake_sections |
3177 |
#define elf_backend_gc_mark_hook v850_elf_gc_mark_hook |
#define elf_backend_gc_mark_hook v850_elf_gc_mark_hook |
3178 |
#define elf_backend_gc_sweep_hook v850_elf_gc_sweep_hook |
#define elf_backend_gc_sweep_hook v850_elf_gc_sweep_hook |
3179 |
|
#define elf_backend_special_sections v850_elf_special_sections |
3180 |
|
|
3181 |
#define elf_backend_can_gc_sections 1 |
#define elf_backend_can_gc_sections 1 |
3182 |
|
#define elf_backend_rela_normal 1 |
3183 |
|
|
3184 |
#define bfd_elf32_bfd_is_local_label_name v850_elf_is_local_label_name |
#define bfd_elf32_bfd_is_local_label_name v850_elf_is_local_label_name |
3185 |
#define bfd_elf32_bfd_reloc_type_lookup v850_elf_reloc_type_lookup |
#define bfd_elf32_bfd_reloc_type_lookup v850_elf_reloc_type_lookup |
3186 |
#define bfd_elf32_bfd_merge_private_bfd_data v850_elf_merge_private_bfd_data |
#define bfd_elf32_bfd_merge_private_bfd_data v850_elf_merge_private_bfd_data |
3187 |
#define bfd_elf32_bfd_set_private_flags v850_elf_set_private_flags |
#define bfd_elf32_bfd_set_private_flags v850_elf_set_private_flags |
3188 |
#define bfd_elf32_bfd_print_private_bfd_data v850_elf_print_private_bfd_data |
#define bfd_elf32_bfd_print_private_bfd_data v850_elf_print_private_bfd_data |
3189 |
|
#define bfd_elf32_bfd_relax_section v850_elf_relax_section |
3190 |
|
|
3191 |
#define elf_symbol_leading_char '_' |
#define elf_symbol_leading_char '_' |
3192 |
|
|