]>
Commit | Line | Data |
---|---|---|
ae1b99e4 JL |
1 | /* Matsushita 10300 specific support for 32-bit ELF |
2 | Copyright (C) 1996 Free Software Foundation, Inc. | |
efc2b064 JL |
3 | |
4 | This file is part of BFD, the Binary File Descriptor library. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
19 | ||
20 | #include "bfd.h" | |
21 | #include "sysdep.h" | |
22 | #include "libbfd.h" | |
23 | #include "elf-bfd.h" | |
24 | ||
25 | static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup | |
26 | PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); | |
943686fa JL |
27 | static void mn10300_info_to_howto |
28 | PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *)); | |
12fdaaf8 JL |
29 | static bfd_reloc_status_type bfd_elf32_mn10300_reloc |
30 | PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); | |
31 | ||
efc2b064 | 32 | |
943686fa JL |
33 | /* We have to use RELA instructions since md_apply_fix3 in the assembler |
34 | does absolutely nothing. */ | |
35 | #define USE_RELA | |
efc2b064 JL |
36 | |
37 | enum reloc_type | |
38 | { | |
ae1b99e4 | 39 | R_MN10300_NONE = 0, |
c3239e66 JL |
40 | R_MN10300_32, |
41 | R_MN10300_16, | |
42 | R_MN10300_8, | |
12fdaaf8 JL |
43 | R_MN10300_PCREL32_1BYTE, |
44 | R_MN10300_PCREL16_1BYTE, | |
45 | R_MN10300_PCREL8_1BYTE, | |
46 | R_MN10300_PCREL32_2BYTE, | |
47 | R_MN10300_PCREL16_2BYTE, | |
ae1b99e4 | 48 | R_MN10300_MAX |
efc2b064 JL |
49 | }; |
50 | ||
ae1b99e4 | 51 | static reloc_howto_type elf_mn10300_howto_table[] = |
efc2b064 | 52 | { |
207e944c | 53 | /* Dummy relocation. Does nothing. */ |
ae1b99e4 | 54 | HOWTO (R_MN10300_NONE, |
efc2b064 JL |
55 | 0, |
56 | 2, | |
57 | 16, | |
58 | false, | |
59 | 0, | |
60 | complain_overflow_bitfield, | |
61 | bfd_elf_generic_reloc, | |
ae1b99e4 | 62 | "R_MN10300_NONE", |
efc2b064 JL |
63 | false, |
64 | 0, | |
65 | 0, | |
66 | false), | |
207e944c | 67 | /* Standard 32 bit reloc. */ |
c3239e66 JL |
68 | HOWTO (R_MN10300_32, |
69 | 0, | |
70 | 2, | |
71 | 32, | |
72 | false, | |
73 | 0, | |
74 | complain_overflow_bitfield, | |
75 | bfd_elf_generic_reloc, | |
76 | "R_MN10300_32", | |
d28f058e | 77 | false, |
c3239e66 JL |
78 | 0xffffffff, |
79 | 0xffffffff, | |
80 | false), | |
207e944c | 81 | /* Standard 16 bit reloc. */ |
c3239e66 JL |
82 | HOWTO (R_MN10300_16, |
83 | 0, | |
84 | 1, | |
85 | 16, | |
86 | false, | |
87 | 0, | |
88 | complain_overflow_bitfield, | |
89 | bfd_elf_generic_reloc, | |
90 | "R_MN10300_16", | |
d28f058e | 91 | false, |
c3239e66 JL |
92 | 0xffff, |
93 | 0xffff, | |
94 | false), | |
207e944c | 95 | /* Standard 8 bit reloc. */ |
c3239e66 JL |
96 | HOWTO (R_MN10300_8, |
97 | 0, | |
98 | 0, | |
99 | 8, | |
100 | false, | |
101 | 0, | |
102 | complain_overflow_bitfield, | |
103 | bfd_elf_generic_reloc, | |
104 | "R_MN10300_8", | |
d28f058e | 105 | false, |
c3239e66 JL |
106 | 0xff, |
107 | 0xff, | |
108 | false), | |
207e944c JL |
109 | /* Simple 32bit pc-relative reloc with a 1 byte adjustment |
110 | to get the pc-relative offset correct. */ | |
12fdaaf8 JL |
111 | HOWTO (R_MN10300_PCREL32_1BYTE, |
112 | 0, | |
113 | 2, | |
114 | 32, | |
115 | true, | |
116 | 0, | |
117 | complain_overflow_bitfield, | |
118 | bfd_elf32_mn10300_reloc, | |
119 | "R_MN10300_PCREL32_1BYTE", | |
c3239e66 JL |
120 | true, |
121 | 0xffffffff, | |
122 | 0xffffffff, | |
123 | false), | |
207e944c JL |
124 | /* Simple 16bit pc-relative reloc with a 1 byte adjustment |
125 | to get the pc-relative offset correct. */ | |
12fdaaf8 | 126 | HOWTO (R_MN10300_PCREL16_1BYTE, |
c3239e66 JL |
127 | 0, |
128 | 1, | |
129 | 16, | |
130 | true, | |
131 | 0, | |
132 | complain_overflow_bitfield, | |
12fdaaf8 JL |
133 | bfd_elf32_mn10300_reloc, |
134 | "R_MN10300_PCREL16_1BYTE", | |
c3239e66 JL |
135 | true, |
136 | 0xffff, | |
137 | 0xffff, | |
138 | false), | |
207e944c JL |
139 | /* Simple 8 pc-relative reloc with a 1 byte adjustment |
140 | to get the pc-relative offset correct. */ | |
12fdaaf8 | 141 | HOWTO (R_MN10300_PCREL8_1BYTE, |
c3239e66 JL |
142 | 0, |
143 | 0, | |
144 | 8, | |
145 | true, | |
146 | 0, | |
147 | complain_overflow_bitfield, | |
12fdaaf8 JL |
148 | bfd_elf32_mn10300_reloc, |
149 | "R_MN10300_PCREL8_1BYTE", | |
c3239e66 JL |
150 | true, |
151 | 0xff, | |
152 | 0xff, | |
12fdaaf8 | 153 | true), |
207e944c JL |
154 | /* Simple 32 pc-relative reloc with a 2 byte adjustment |
155 | to get the pc-relative offset correct. */ | |
12fdaaf8 JL |
156 | HOWTO (R_MN10300_PCREL32_2BYTE, |
157 | 0, | |
158 | 2, | |
159 | 32, | |
160 | true, | |
161 | 0, | |
162 | complain_overflow_bitfield, | |
163 | bfd_elf32_mn10300_reloc, | |
164 | "R_MN10300_PCREL32_2BYTE", | |
165 | true, | |
166 | 0xffffffff, | |
167 | 0xffffffff, | |
168 | true), | |
207e944c JL |
169 | /* Simple 16 pc-relative reloc with a 2 byte adjustment |
170 | to get the pc-relative offset correct. */ | |
12fdaaf8 JL |
171 | HOWTO (R_MN10300_PCREL16_2BYTE, |
172 | 0, | |
173 | 1, | |
174 | 16, | |
175 | true, | |
176 | 0, | |
177 | complain_overflow_bitfield, | |
178 | bfd_elf32_mn10300_reloc, | |
179 | "R_MN10300_PCREL16_2BYTE", | |
180 | true, | |
181 | 0xffff, | |
182 | 0xffff, | |
183 | true), | |
efc2b064 JL |
184 | }; |
185 | ||
ae1b99e4 | 186 | struct mn10300_reloc_map |
efc2b064 JL |
187 | { |
188 | unsigned char bfd_reloc_val; | |
189 | unsigned char elf_reloc_val; | |
190 | }; | |
191 | ||
ae1b99e4 | 192 | static const struct mn10300_reloc_map mn10300_reloc_map[] = |
efc2b064 | 193 | { |
ae1b99e4 | 194 | { BFD_RELOC_NONE, R_MN10300_NONE, }, |
c3239e66 JL |
195 | { BFD_RELOC_32, R_MN10300_32, }, |
196 | { BFD_RELOC_16, R_MN10300_16, }, | |
197 | { BFD_RELOC_8, R_MN10300_8, }, | |
12fdaaf8 JL |
198 | { BFD_RELOC_32_PCREL, R_MN10300_PCREL32_1BYTE, }, |
199 | { BFD_RELOC_16_PCREL, R_MN10300_PCREL16_1BYTE, }, | |
200 | { BFD_RELOC_8_PCREL, R_MN10300_PCREL8_1BYTE, }, | |
201 | { BFD_RELOC_MN10300_32_PCREL, R_MN10300_PCREL32_2BYTE, }, | |
202 | { BFD_RELOC_MN10300_16_PCREL, R_MN10300_PCREL16_2BYTE, }, | |
efc2b064 JL |
203 | }; |
204 | ||
205 | static reloc_howto_type * | |
206 | bfd_elf32_bfd_reloc_type_lookup (abfd, code) | |
207 | bfd *abfd; | |
208 | bfd_reloc_code_real_type code; | |
209 | { | |
210 | unsigned int i; | |
211 | ||
212 | for (i = 0; | |
ae1b99e4 | 213 | i < sizeof (mn10300_reloc_map) / sizeof (struct mn10300_reloc_map); |
efc2b064 JL |
214 | i++) |
215 | { | |
ae1b99e4 JL |
216 | if (mn10300_reloc_map[i].bfd_reloc_val == code) |
217 | return &elf_mn10300_howto_table[mn10300_reloc_map[i].elf_reloc_val]; | |
efc2b064 JL |
218 | } |
219 | ||
220 | return NULL; | |
221 | } | |
222 | ||
12fdaaf8 | 223 | /* Set the howto pointer for an MN10300 ELF reloc. */ |
efc2b064 JL |
224 | |
225 | static void | |
943686fa | 226 | mn10300_info_to_howto (abfd, cache_ptr, dst) |
efc2b064 JL |
227 | bfd *abfd; |
228 | arelent *cache_ptr; | |
943686fa | 229 | Elf32_Internal_Rela *dst; |
efc2b064 JL |
230 | { |
231 | unsigned int r_type; | |
232 | ||
233 | r_type = ELF32_R_TYPE (dst->r_info); | |
ae1b99e4 JL |
234 | BFD_ASSERT (r_type < (unsigned int) R_MN10300_MAX); |
235 | cache_ptr->howto = &elf_mn10300_howto_table[r_type]; | |
efc2b064 JL |
236 | } |
237 | ||
12fdaaf8 JL |
238 | static bfd_reloc_status_type |
239 | bfd_elf32_mn10300_reloc (abfd, reloc, symbol, data, isection, obfd, err) | |
240 | bfd *abfd; | |
241 | arelent *reloc; | |
242 | asymbol *symbol; | |
243 | PTR data; | |
244 | asection *isection; | |
245 | bfd *obfd; | |
246 | char **err; | |
247 | { | |
248 | if (obfd != (bfd *) NULL | |
249 | && (symbol->flags & BSF_SECTION_SYM) == 0 | |
250 | && (! reloc->howto->partial_inplace | |
251 | || reloc->addend == 0)) | |
252 | { | |
253 | reloc->address += isection->output_offset; | |
254 | return bfd_reloc_ok; | |
255 | } | |
256 | else if (obfd != NULL) | |
257 | { | |
258 | return bfd_reloc_continue; | |
259 | } | |
260 | ||
261 | /* Catch relocs involving undefined symbols. */ | |
262 | if (bfd_is_und_section (symbol->section) | |
263 | && (symbol->flags & BSF_WEAK) == 0 | |
264 | && obfd == NULL) | |
265 | return bfd_reloc_undefined; | |
266 | ||
267 | /* We handle final linking of some relocs ourselves. */ | |
268 | { | |
207e944c | 269 | long relocation; |
12fdaaf8 JL |
270 | |
271 | /* Is the address of the relocation really within the section? */ | |
272 | if (reloc->address > isection->_cooked_size) | |
273 | return bfd_reloc_outofrange; | |
274 | ||
275 | /* Work out which section the relocation is targetted at and the | |
276 | initial relocation command value. */ | |
277 | ||
278 | /* Get symbol value. (Common symbols are special.) */ | |
279 | if (bfd_is_com_section (symbol->section)) | |
280 | relocation = 0; | |
281 | else | |
282 | relocation = symbol->value; | |
283 | ||
284 | /* Convert input-section-relative symbol value to absolute + addend. */ | |
285 | relocation += symbol->section->output_section->vma; | |
286 | relocation += symbol->section->output_offset; | |
287 | relocation += reloc->addend; | |
288 | ||
289 | if (reloc->howto->pc_relative == true) | |
290 | { | |
291 | /* Here the variable relocation holds the final address of the | |
292 | symbol we are relocating against, plus any addend. */ | |
293 | relocation -= isection->output_section->vma + isection->output_offset; | |
294 | ||
295 | /* Deal with pcrel_offset */ | |
296 | relocation -= reloc->address; | |
297 | ||
298 | if (reloc->howto->type == R_MN10300_PCREL32_1BYTE | |
299 | || reloc->howto->type == R_MN10300_PCREL16_1BYTE | |
300 | || reloc->howto->type == R_MN10300_PCREL8_1BYTE) | |
301 | relocation += 1; | |
302 | else if (reloc->howto->type == R_MN10300_PCREL32_2BYTE | |
303 | || reloc->howto->type == R_MN10300_PCREL16_2BYTE) | |
304 | relocation += 2; | |
305 | } | |
306 | ||
307 | /* I've got no clue... */ | |
308 | reloc->addend = 0; | |
309 | ||
310 | if (reloc->howto->size == 0) | |
311 | { | |
312 | if (relocation > 0x7f || relocation < -0x80) | |
313 | return bfd_reloc_overflow; | |
314 | ||
315 | bfd_put_8 (abfd, relocation & 0xff, | |
316 | (bfd_byte *)data + reloc->address); | |
317 | } | |
318 | else if (reloc->howto->size == 1) | |
319 | { | |
320 | if (relocation > 0x7fff || relocation < -0x8000) | |
321 | return bfd_reloc_overflow; | |
322 | ||
e14af8fc JL |
323 | bfd_put_16 (abfd, relocation & 0xffff, |
324 | (bfd_byte *)data + reloc->address); | |
12fdaaf8 JL |
325 | } |
326 | else if (reloc->howto->size == 2) | |
e14af8fc | 327 | bfd_put_32 (abfd, relocation, (bfd_byte *)data + reloc->address); |
12fdaaf8 JL |
328 | return bfd_reloc_ok; |
329 | } | |
330 | ||
331 | return bfd_reloc_continue; | |
332 | } | |
333 | ||
ae1b99e4 JL |
334 | #define TARGET_LITTLE_SYM bfd_elf32_mn10300_vec |
335 | #define TARGET_LITTLE_NAME "elf32-mn10300" | |
336 | #define ELF_ARCH bfd_arch_mn10300 | |
337 | #define ELF_MACHINE_CODE EM_CYGNUS_MN10300 | |
efc2b064 JL |
338 | #define ELF_MAXPAGESIZE 0x1000 |
339 | ||
943686fa JL |
340 | #define elf_info_to_howto mn10300_info_to_howto |
341 | #define elf_info_to_howto_rel 0 | |
efc2b064 | 342 | |
31cffd2e JL |
343 | #define elf_symbol_leading_char '_' |
344 | ||
efc2b064 | 345 | #include "elf32-target.h" |