f5fd41309d7b5e85dee04e6e89161b7c070afd64
[deliverable/binutils-gdb.git] / bfd / elfarm-nabi.c
1 /* 32-bit ELF support for ARM new abi option.
2 Copyright 1999 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 "elf/arm.h"
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "elf-bfd.h"
25
26 #define USE_REL
27
28 #define TARGET_LITTLE_SYM bfd_elf32_littlearm_vec
29 #define TARGET_LITTLE_NAME "elf32-littlearm"
30 #define TARGET_BIG_SYM bfd_elf32_bigarm_vec
31 #define TARGET_BIG_NAME "elf32-bigarm"
32 #define elf_info_to_howto 0
33 #define elf_info_to_howto_rel elf32_arm_info_to_howto_rel
34
35
36 static reloc_howto_type *elf32_arm_reloc_type_lookup
37 PARAMS ((bfd * abfd, bfd_reloc_code_real_type code));
38
39 static reloc_howto_type elf32_arm_howto_table[] =
40 {
41 /* No relocation */
42 HOWTO (R_ARM_NONE, /* type */
43 0, /* rightshift */
44 0, /* size (0 = byte, 1 = short, 2 = long) */
45 0, /* bitsize */
46 false, /* pc_relative */
47 0, /* bitpos */
48 complain_overflow_dont, /* complain_on_overflow */
49 bfd_elf_generic_reloc, /* special_function */
50 "R_ARM_NONE", /* name */
51 false, /* partial_inplace */
52 0, /* src_mask */
53 0, /* dst_mask */
54 false), /* pcrel_offset */
55
56 HOWTO (R_ARM_PC24, /* type */
57 2, /* rightshift */
58 2, /* size (0 = byte, 1 = short, 2 = long) */
59 24, /* bitsize */
60 true, /* pc_relative */
61 0, /* bitpos */
62 complain_overflow_signed, /* complain_on_overflow */
63 bfd_elf_generic_reloc, /* special_function */
64 "R_ARM_PC24", /* name */
65 false, /* partial_inplace */
66 0x00ffffff, /* src_mask */
67 0x00ffffff, /* dst_mask */
68 true), /* pcrel_offset */
69
70 /* 32 bit absolute */
71 HOWTO (R_ARM_ABS32, /* type */
72 0, /* rightshift */
73 2, /* size (0 = byte, 1 = short, 2 = long) */
74 32, /* bitsize */
75 false, /* pc_relative */
76 0, /* bitpos */
77 complain_overflow_bitfield, /* complain_on_overflow */
78 bfd_elf_generic_reloc, /* special_function */
79 "R_ARM_ABS32", /* name */
80 false, /* partial_inplace */
81 0xffffffff, /* src_mask */
82 0xffffffff, /* dst_mask */
83 false), /* pcrel_offset */
84
85 /* standard 32bit pc-relative reloc */
86 HOWTO (R_ARM_REL32, /* type */
87 0, /* rightshift */
88 2, /* size (0 = byte, 1 = short, 2 = long) */
89 32, /* bitsize */
90 true, /* pc_relative */
91 0, /* bitpos */
92 complain_overflow_bitfield, /* complain_on_overflow */
93 bfd_elf_generic_reloc, /* special_function */
94 "R_ARM_REL32", /* name */
95 false, /* partial_inplace */
96 0xffffffff, /* src_mask */
97 0xffffffff, /* dst_mask */
98 true), /* pcrel_offset */
99
100 /* 8 bit absolute */
101 HOWTO (R_ARM_PC13, /* type */
102 0, /* rightshift */
103 0, /* size (0 = byte, 1 = short, 2 = long) */
104 8, /* bitsize */
105 false, /* pc_relative */
106 0, /* bitpos */
107 complain_overflow_bitfield, /* complain_on_overflow */
108 bfd_elf_generic_reloc, /* special_function */
109 "R_ARM_PC13", /* name */
110 false, /* partial_inplace */
111 0x000000ff, /* src_mask */
112 0x000000ff, /* dst_mask */
113 false), /* pcrel_offset */
114
115 /* 16 bit absolute */
116 HOWTO (R_ARM_ABS16, /* type */
117 0, /* rightshift */
118 1, /* size (0 = byte, 1 = short, 2 = long) */
119 16, /* bitsize */
120 false, /* pc_relative */
121 0, /* bitpos */
122 complain_overflow_bitfield, /* complain_on_overflow */
123 bfd_elf_generic_reloc, /* special_function */
124 "R_ARM_ABS16", /* name */
125 false, /* partial_inplace */
126 0, /* src_mask */
127 0, /* dst_mask */
128 false), /* pcrel_offset */
129
130 /* 12 bit absolute */
131 HOWTO (R_ARM_ABS12, /* type */
132 0, /* rightshift */
133 2, /* size (0 = byte, 1 = short, 2 = long) */
134 12, /* bitsize */
135 false, /* pc_relative */
136 0, /* bitpos */
137 complain_overflow_bitfield, /* complain_on_overflow */
138 bfd_elf_generic_reloc, /* special_function */
139 "R_ARM_ABS12", /* name */
140 false, /* partial_inplace */
141 0x000008ff, /* src_mask */
142 0x000008ff, /* dst_mask */
143 false), /* pcrel_offset */
144
145 HOWTO (R_ARM_THM_ABS5, /* type */
146 0, /* rightshift */
147 2, /* size (0 = byte, 1 = short, 2 = long) */
148 5, /* bitsize */
149 false, /* pc_relative */
150 0, /* bitpos */
151 complain_overflow_bitfield, /* complain_on_overflow */
152 bfd_elf_generic_reloc, /* special_function */
153 "R_ARM_THM_ABS5", /* name */
154 false, /* partial_inplace */
155 0x000007e0, /* src_mask */
156 0x000007e0, /* dst_mask */
157 false), /* pcrel_offset */
158
159 /* 8 bit absolute */
160 HOWTO (R_ARM_ABS8, /* type */
161 0, /* rightshift */
162 0, /* size (0 = byte, 1 = short, 2 = long) */
163 8, /* bitsize */
164 false, /* pc_relative */
165 0, /* bitpos */
166 complain_overflow_bitfield, /* complain_on_overflow */
167 bfd_elf_generic_reloc, /* special_function */
168 "R_ARM_ABS8", /* name */
169 false, /* partial_inplace */
170 0x000000ff, /* src_mask */
171 0x000000ff, /* dst_mask */
172 false), /* pcrel_offset */
173
174 HOWTO (R_ARM_SBREL32, /* type */
175 0, /* rightshift */
176 0, /* size (0 = byte, 1 = short, 2 = long) */
177 0, /* bitsize */
178 false, /* pc_relative */
179 0, /* bitpos */
180 complain_overflow_dont, /* complain_on_overflow */
181 bfd_elf_generic_reloc, /* special_function */
182 "R_ARM_SBREL32", /* name */
183 false, /* partial_inplace */
184 0, /* src_mask */
185 0, /* dst_mask */
186 false), /* pcrel_offset */
187
188 HOWTO (R_ARM_THM_PC22, /* type */
189 1, /* rightshift */
190 2, /* size (0 = byte, 1 = short, 2 = long) */
191 22, /* bitsize */
192 true, /* pc_relative */
193 0, /* bitpos */
194 complain_overflow_signed, /* complain_on_overflow */
195 bfd_elf_generic_reloc, /* special_function */
196 "R_ARM_THM_PC22", /* name */
197 false, /* partial_inplace */
198 0x07ff07ff, /* src_mask */
199 0x07ff07ff, /* dst_mask */
200 true), /* pcrel_offset */
201
202 HOWTO (R_ARM_THM_PC8, /* type */
203 1, /* rightshift */
204 1, /* size (0 = byte, 1 = short, 2 = long) */
205 8, /* bitsize */
206 true, /* pc_relative */
207 0, /* bitpos */
208 complain_overflow_signed, /* complain_on_overflow */
209 bfd_elf_generic_reloc, /* special_function */
210 "R_ARM_THM_PC8", /* name */
211 false, /* partial_inplace */
212 0x000000ff, /* src_mask */
213 0x000000ff, /* dst_mask */
214 true), /* pcrel_offset */
215
216 HOWTO (R_ARM_AMP_VCALL9, /* type */
217 1, /* rightshift */
218 1, /* size (0 = byte, 1 = short, 2 = long) */
219 8, /* bitsize */
220 true, /* pc_relative */
221 0, /* bitpos */
222 complain_overflow_signed, /* complain_on_overflow */
223 bfd_elf_generic_reloc, /* special_function */
224 "R_ARM_AMP_VCALL9", /* name */
225 false, /* partial_inplace */
226 0x000000ff, /* src_mask */
227 0x000000ff, /* dst_mask */
228 true), /* pcrel_offset */
229
230 HOWTO (R_ARM_SWI24, /* type */
231 0, /* rightshift */
232 0, /* size (0 = byte, 1 = short, 2 = long) */
233 0, /* bitsize */
234 false, /* pc_relative */
235 0, /* bitpos */
236 complain_overflow_signed, /* complain_on_overflow */
237 bfd_elf_generic_reloc, /* special_function */
238 "R_ARM_SWI24", /* name */
239 false, /* partial_inplace */
240 0x00000000, /* src_mask */
241 0x00000000, /* dst_mask */
242 false), /* pcrel_offset */
243
244 HOWTO (R_ARM_THM_SWI8, /* type */
245 0, /* rightshift */
246 0, /* size (0 = byte, 1 = short, 2 = long) */
247 0, /* bitsize */
248 false, /* pc_relative */
249 0, /* bitpos */
250 complain_overflow_signed, /* complain_on_overflow */
251 bfd_elf_generic_reloc, /* special_function */
252 "R_ARM_SWI8", /* name */
253 false, /* partial_inplace */
254 0x00000000, /* src_mask */
255 0x00000000, /* dst_mask */
256 false), /* pcrel_offset */
257
258 HOWTO (R_ARM_RREL32, /* type */
259 0, /* rightshift */
260 0, /* size (0 = byte, 1 = short, 2 = long) */
261 0, /* bitsize */
262 false, /* pc_relative */
263 0, /* bitpos */
264 complain_overflow_dont, /* complain_on_overflow */
265 bfd_elf_generic_reloc, /* special_function */
266 "R_ARM_RREL32", /* name */
267 false, /* partial_inplace */
268 0, /* src_mask */
269 0, /* dst_mask */
270 false), /* pcrel_offset */
271
272 HOWTO (R_ARM_RABS32, /* type */
273 0, /* rightshift */
274 0, /* size (0 = byte, 1 = short, 2 = long) */
275 0, /* bitsize */
276 false, /* pc_relative */
277 0, /* bitpos */
278 complain_overflow_dont, /* complain_on_overflow */
279 bfd_elf_generic_reloc, /* special_function */
280 "R_ARM_RABS32", /* name */
281 false, /* partial_inplace */
282 0, /* src_mask */
283 0, /* dst_mask */
284 false), /* pcrel_offset */
285
286 HOWTO (R_ARM_RPC24, /* type */
287 0, /* rightshift */
288 0, /* size (0 = byte, 1 = short, 2 = long) */
289 0, /* bitsize */
290 false, /* pc_relative */
291 0, /* bitpos */
292 complain_overflow_dont, /* complain_on_overflow */
293 bfd_elf_generic_reloc, /* special_function */
294 "R_ARM_RPC24", /* name */
295 false, /* partial_inplace */
296 0, /* src_mask */
297 0, /* dst_mask */
298 false), /* pcrel_offset */
299
300 HOWTO (R_ARM_RBASE, /* type */
301 0, /* rightshift */
302 0, /* size (0 = byte, 1 = short, 2 = long) */
303 0, /* bitsize */
304 false, /* pc_relative */
305 0, /* bitpos */
306 complain_overflow_dont, /* complain_on_overflow */
307 bfd_elf_generic_reloc, /* special_function */
308 "R_ARM_RBASE", /* name */
309 false, /* partial_inplace */
310 0, /* src_mask */
311 0, /* dst_mask */
312 false), /* pcrel_offset */
313
314 };
315
316 /* GNU extension to record C++ vtable hierarchy */
317 static reloc_howto_type elf32_arm_vtinherit_howto =
318 HOWTO (R_ARM_GNU_VTINHERIT, /* type */
319 0, /* rightshift */
320 2, /* size (0 = byte, 1 = short, 2 = long) */
321 0, /* bitsize */
322 false, /* pc_relative */
323 0, /* bitpos */
324 complain_overflow_dont, /* complain_on_overflow */
325 NULL, /* special_function */
326 "R_ARM_GNU_VTINHERIT", /* name */
327 false, /* partial_inplace */
328 0, /* src_mask */
329 0, /* dst_mask */
330 false); /* pcrel_offset */
331
332 /* GNU extension to record C++ vtable member usage */
333 static reloc_howto_type elf32_arm_vtentry_howto =
334 HOWTO (R_ARM_GNU_VTENTRY, /* type */
335 0, /* rightshift */
336 2, /* size (0 = byte, 1 = short, 2 = long) */
337 0, /* bitsize */
338 false, /* pc_relative */
339 0, /* bitpos */
340 complain_overflow_dont, /* complain_on_overflow */
341 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
342 "R_ARM_GNU_VTENTRY", /* name */
343 false, /* partial_inplace */
344 0, /* src_mask */
345 0, /* dst_mask */
346 false); /* pcrel_offset */
347
348 /* 12 bit pc relative */
349 static reloc_howto_type elf32_arm_thm_pc11_howto =
350 HOWTO (R_ARM_THM_PC11, /* type */
351 1, /* rightshift */
352 1, /* size (0 = byte, 1 = short, 2 = long) */
353 11, /* bitsize */
354 true, /* pc_relative */
355 0, /* bitpos */
356 complain_overflow_signed, /* complain_on_overflow */
357 bfd_elf_generic_reloc, /* special_function */
358 "R_ARM_THM_PC11", /* name */
359 false, /* partial_inplace */
360 0x000007ff, /* src_mask */
361 0x000007ff, /* dst_mask */
362 true); /* pcrel_offset */
363
364 /* 12 bit pc relative */
365 static reloc_howto_type elf32_arm_thm_pc9_howto =
366 HOWTO (R_ARM_THM_PC9, /* type */
367 1, /* rightshift */
368 1, /* size (0 = byte, 1 = short, 2 = long) */
369 8, /* bitsize */
370 true, /* pc_relative */
371 0, /* bitpos */
372 complain_overflow_signed, /* complain_on_overflow */
373 bfd_elf_generic_reloc, /* special_function */
374 "R_ARM_THM_PC9", /* name */
375 false, /* partial_inplace */
376 0x000000ff, /* src_mask */
377 0x000000ff, /* dst_mask */
378 true); /* pcrel_offset */
379
380
381 static void
382 elf32_arm_info_to_howto_rel (abfd, bfd_reloc, elf_reloc)
383 bfd *abfd;
384 arelent *bfd_reloc;
385 Elf32_Internal_Rel *elf_reloc;
386 {
387 unsigned int r_type;
388
389 r_type = ELF32_R_TYPE (elf_reloc->r_info);
390 if (r_type == R_ARM_GNU_VTINHERIT)
391 bfd_reloc->howto = &elf32_arm_vtinherit_howto;
392 else if (r_type == R_ARM_GNU_VTENTRY)
393 bfd_reloc->howto = &elf32_arm_vtentry_howto;
394 else if (r_type == R_ARM_THM_PC11)
395 bfd_reloc->howto = &elf32_arm_thm_pc11_howto;
396 else if (r_type == R_ARM_THM_PC9)
397 bfd_reloc->howto = &elf32_arm_thm_pc9_howto;
398 else
399 bfd_reloc->howto = &elf32_arm_howto_table[r_type];
400 }
401
402 struct elf32_arm_reloc_map
403 {
404 unsigned char bfd_reloc_val;
405 unsigned char elf_reloc_val;
406 };
407
408 static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
409 {
410 {BFD_RELOC_NONE, R_ARM_NONE,},
411 {BFD_RELOC_ARM_PCREL_BRANCH, R_ARM_PC24,},
412 {BFD_RELOC_32, R_ARM_ABS32,},
413 {BFD_RELOC_32_PCREL, R_ARM_REL32,},
414 {BFD_RELOC_8, R_ARM_ABS8,},
415 {BFD_RELOC_16, R_ARM_ABS16,},
416 {BFD_RELOC_ARM_OFFSET_IMM, R_ARM_ABS12,},
417 {BFD_RELOC_ARM_THUMB_OFFSET, R_ARM_THM_ABS5,},
418 {BFD_RELOC_THUMB_PCREL_BRANCH23, R_ARM_THM_PC22,},
419 {BFD_RELOC_VTABLE_INHERIT, R_ARM_GNU_VTINHERIT },
420 {BFD_RELOC_VTABLE_ENTRY, R_ARM_GNU_VTENTRY },
421 {BFD_RELOC_NONE, R_ARM_SBREL32,},
422 {BFD_RELOC_NONE, R_ARM_AMP_VCALL9,},
423 {BFD_RELOC_THUMB_PCREL_BRANCH12, R_ARM_THM_PC11,},
424 {BFD_RELOC_THUMB_PCREL_BRANCH9, R_ARM_THM_PC9,}
425 };
426
427 static reloc_howto_type *
428 elf32_arm_reloc_type_lookup (abfd, code)
429 bfd *abfd;
430 bfd_reloc_code_real_type code;
431 {
432 unsigned int i;
433
434 switch (code)
435 {
436 case BFD_RELOC_VTABLE_INHERIT:
437 return &elf32_arm_vtinherit_howto;
438
439 case BFD_RELOC_VTABLE_ENTRY:
440 return &elf32_arm_vtentry_howto;
441
442 case BFD_RELOC_THUMB_PCREL_BRANCH12:
443 return &elf32_arm_thm_pc11_howto;
444
445 case BFD_RELOC_THUMB_PCREL_BRANCH9:
446 return &elf32_arm_thm_pc9_howto;
447
448 default:
449 for (i = 0;
450 i < sizeof (elf32_arm_reloc_map) / sizeof (struct elf32_arm_reloc_map);
451 i++)
452 {
453 if (elf32_arm_reloc_map[i].bfd_reloc_val == code)
454 return &elf32_arm_howto_table[elf32_arm_reloc_map[i].elf_reloc_val];
455 }
456
457 }
458 return NULL;
459 }
460
461 #include "elf32-arm.h"
This page took 0.052867 seconds and 4 git commands to generate.