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