1 /* 32-bit ELF support for ARM new abi option.
2 Copyright 1999 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
27 #define NUM_ELEM(a) (sizeof (a) / (sizeof (a)[0]))
32 #define TARGET_LITTLE_SYM bfd_elf32_littlearm_vec
33 #define TARGET_LITTLE_NAME "elf32-littlearm"
34 #define TARGET_BIG_SYM bfd_elf32_bigarm_vec
35 #define TARGET_BIG_NAME "elf32-bigarm"
37 #define elf_info_to_howto 0
38 #define elf_info_to_howto_rel elf32_arm_info_to_howto_rel
41 static reloc_howto_type * elf32_arm_reloc_type_lookup
42 PARAMS ((bfd * abfd, bfd_reloc_code_real_type code));
44 static reloc_howto_type elf32_arm_howto_table[] =
47 HOWTO (R_ARM_NONE, /* type */
49 0, /* size (0 = byte, 1 = short, 2 = long) */
51 false, /* pc_relative */
53 complain_overflow_dont,/* complain_on_overflow */
54 bfd_elf_generic_reloc, /* special_function */
55 "R_ARM_NONE", /* name */
56 false, /* partial_inplace */
59 false), /* pcrel_offset */
61 HOWTO (R_ARM_PC24, /* type */
63 2, /* size (0 = byte, 1 = short, 2 = long) */
65 true, /* pc_relative */
67 complain_overflow_signed,/* complain_on_overflow */
68 bfd_elf_generic_reloc, /* special_function */
69 "R_ARM_PC24", /* name */
70 false, /* partial_inplace */
71 0x00ffffff, /* src_mask */
72 0x00ffffff, /* dst_mask */
73 true), /* pcrel_offset */
76 HOWTO (R_ARM_ABS32, /* type */
78 2, /* size (0 = byte, 1 = short, 2 = long) */
80 false, /* pc_relative */
82 complain_overflow_bitfield,/* complain_on_overflow */
83 bfd_elf_generic_reloc, /* special_function */
84 "R_ARM_ABS32", /* name */
85 false, /* partial_inplace */
86 0xffffffff, /* src_mask */
87 0xffffffff, /* dst_mask */
88 false), /* pcrel_offset */
90 /* standard 32bit pc-relative reloc */
91 HOWTO (R_ARM_REL32, /* type */
93 2, /* size (0 = byte, 1 = short, 2 = long) */
95 true, /* pc_relative */
97 complain_overflow_bitfield,/* complain_on_overflow */
98 bfd_elf_generic_reloc, /* special_function */
99 "R_ARM_REL32", /* name */
100 false, /* partial_inplace */
101 0xffffffff, /* src_mask */
102 0xffffffff, /* dst_mask */
103 true), /* pcrel_offset */
106 HOWTO (R_ARM_PC13, /* type */
108 0, /* size (0 = byte, 1 = short, 2 = long) */
110 false, /* pc_relative */
112 complain_overflow_bitfield,/* complain_on_overflow */
113 bfd_elf_generic_reloc, /* special_function */
114 "R_ARM_PC13", /* name */
115 false, /* partial_inplace */
116 0x000000ff, /* src_mask */
117 0x000000ff, /* dst_mask */
118 false), /* pcrel_offset */
120 /* 16 bit absolute */
121 HOWTO (R_ARM_ABS16, /* type */
123 1, /* size (0 = byte, 1 = short, 2 = long) */
125 false, /* pc_relative */
127 complain_overflow_bitfield,/* complain_on_overflow */
128 bfd_elf_generic_reloc, /* special_function */
129 "R_ARM_ABS16", /* name */
130 false, /* partial_inplace */
133 false), /* pcrel_offset */
135 /* 12 bit absolute */
136 HOWTO (R_ARM_ABS12, /* type */
138 2, /* size (0 = byte, 1 = short, 2 = long) */
140 false, /* pc_relative */
142 complain_overflow_bitfield,/* complain_on_overflow */
143 bfd_elf_generic_reloc, /* special_function */
144 "R_ARM_ABS12", /* name */
145 false, /* partial_inplace */
146 0x000008ff, /* src_mask */
147 0x000008ff, /* dst_mask */
148 false), /* pcrel_offset */
150 HOWTO (R_ARM_THM_ABS5, /* type */
152 1, /* size (0 = byte, 1 = short, 2 = long) */
154 false, /* pc_relative */
156 complain_overflow_bitfield,/* complain_on_overflow */
157 bfd_elf_generic_reloc, /* special_function */
158 "R_ARM_THM_ABS5", /* name */
159 false, /* partial_inplace */
160 0x000007e0, /* src_mask */
161 0x000007e0, /* dst_mask */
162 false), /* pcrel_offset */
165 HOWTO (R_ARM_ABS8, /* type */
167 0, /* size (0 = byte, 1 = short, 2 = long) */
169 false, /* pc_relative */
171 complain_overflow_bitfield,/* complain_on_overflow */
172 bfd_elf_generic_reloc, /* special_function */
173 "R_ARM_ABS8", /* name */
174 false, /* partial_inplace */
175 0x000000ff, /* src_mask */
176 0x000000ff, /* dst_mask */
177 false), /* pcrel_offset */
179 HOWTO (R_ARM_SBREL32, /* type */
181 0, /* size (0 = byte, 1 = short, 2 = long) */
183 false, /* pc_relative */
185 complain_overflow_dont,/* complain_on_overflow */
186 bfd_elf_generic_reloc, /* special_function */
187 "R_ARM_SBREL32", /* name */
188 false, /* partial_inplace */
191 false), /* pcrel_offset */
193 HOWTO (R_ARM_THM_PC22, /* type */
195 2, /* size (0 = byte, 1 = short, 2 = long) */
197 true, /* pc_relative */
199 complain_overflow_signed,/* complain_on_overflow */
200 bfd_elf_generic_reloc, /* special_function */
201 "R_ARM_THM_PC22", /* name */
202 false, /* partial_inplace */
203 0x07ff07ff, /* src_mask */
204 0x07ff07ff, /* dst_mask */
205 true), /* pcrel_offset */
207 HOWTO (R_ARM_THM_PC8, /* type */
209 1, /* size (0 = byte, 1 = short, 2 = long) */
211 true, /* pc_relative */
213 complain_overflow_signed,/* complain_on_overflow */
214 bfd_elf_generic_reloc, /* special_function */
215 "R_ARM_THM_PC8", /* name */
216 false, /* partial_inplace */
217 0x000000ff, /* src_mask */
218 0x000000ff, /* dst_mask */
219 true), /* pcrel_offset */
221 HOWTO (R_ARM_AMP_VCALL9, /* type */
223 1, /* size (0 = byte, 1 = short, 2 = long) */
225 true, /* pc_relative */
227 complain_overflow_signed,/* complain_on_overflow */
228 bfd_elf_generic_reloc, /* special_function */
229 "R_ARM_AMP_VCALL9", /* name */
230 false, /* partial_inplace */
231 0x000000ff, /* src_mask */
232 0x000000ff, /* dst_mask */
233 true), /* pcrel_offset */
235 HOWTO (R_ARM_SWI24, /* type */
237 0, /* size (0 = byte, 1 = short, 2 = long) */
239 false, /* pc_relative */
241 complain_overflow_signed,/* complain_on_overflow */
242 bfd_elf_generic_reloc, /* special_function */
243 "R_ARM_SWI24", /* name */
244 false, /* partial_inplace */
245 0x00000000, /* src_mask */
246 0x00000000, /* dst_mask */
247 false), /* pcrel_offset */
249 HOWTO (R_ARM_THM_SWI8, /* type */
251 0, /* size (0 = byte, 1 = short, 2 = long) */
253 false, /* pc_relative */
255 complain_overflow_signed,/* complain_on_overflow */
256 bfd_elf_generic_reloc, /* special_function */
257 "R_ARM_SWI8", /* name */
258 false, /* partial_inplace */
259 0x00000000, /* src_mask */
260 0x00000000, /* dst_mask */
261 false), /* pcrel_offset */
263 /* These next two relocs are defined, but I do not know what they do. */
265 HOWTO (R_ARM_XPC25, /* type */
267 0, /* size (0 = byte, 1 = short, 2 = long) */
269 false, /* pc_relative */
271 complain_overflow_signed,/* complain_on_overflow */
272 bfd_elf_generic_reloc, /* special_function */
273 "R_ARM_XPC25", /* name */
274 false, /* partial_inplace */
275 0x00000000, /* src_mask */
276 0x00000000, /* dst_mask */
277 false), /* pcrel_offset */
279 HOWTO (R_ARM_THM_XPC22, /* type */
281 0, /* size (0 = byte, 1 = short, 2 = long) */
283 false, /* pc_relative */
285 complain_overflow_signed,/* complain_on_overflow */
286 bfd_elf_generic_reloc, /* special_function */
287 "R_ARM_THM_XPC22", /* name */
288 false, /* partial_inplace */
289 0x00000000, /* src_mask */
290 0x00000000, /* dst_mask */
291 false), /* pcrel_offset */
293 /* These next three relocs are not defined, but we need to fill the space. */
295 HOWTO (R_ARM_NONE, /* type */
297 0, /* size (0 = byte, 1 = short, 2 = long) */
299 false, /* pc_relative */
301 complain_overflow_dont,/* complain_on_overflow */
302 bfd_elf_generic_reloc, /* special_function */
303 "R_ARM_unknown_17", /* name */
304 false, /* partial_inplace */
307 false), /* pcrel_offset */
309 HOWTO (R_ARM_NONE, /* type */
311 0, /* size (0 = byte, 1 = short, 2 = long) */
313 false, /* pc_relative */
315 complain_overflow_dont,/* complain_on_overflow */
316 bfd_elf_generic_reloc, /* special_function */
317 "R_ARM_unknown_18", /* name */
318 false, /* partial_inplace */
321 false), /* pcrel_offset */
323 HOWTO (R_ARM_NONE, /* type */
325 0, /* size (0 = byte, 1 = short, 2 = long) */
327 false, /* pc_relative */
329 complain_overflow_dont,/* complain_on_overflow */
330 bfd_elf_generic_reloc, /* special_function */
331 "R_ARM_unknown_19", /* name */
332 false, /* partial_inplace */
335 false), /* pcrel_offset */
337 /* Relocs used in ARM Linux */
339 HOWTO (R_ARM_COPY, /* type */
341 2, /* size (0 = byte, 1 = short, 2 = long) */
343 false, /* pc_relative */
345 complain_overflow_bitfield,/* complain_on_overflow */
346 bfd_elf_generic_reloc, /* special_function */
347 "R_ARM_COPY", /* name */
348 true, /* partial_inplace */
349 0xffffffff, /* src_mask */
350 0xffffffff, /* dst_mask */
351 false), /* pcrel_offset */
353 HOWTO (R_ARM_GLOB_DAT, /* type */
355 2, /* size (0 = byte, 1 = short, 2 = long) */
357 false, /* pc_relative */
359 complain_overflow_bitfield,/* complain_on_overflow */
360 bfd_elf_generic_reloc, /* special_function */
361 "R_ARM_GLOB_DAT", /* name */
362 true, /* partial_inplace */
363 0xffffffff, /* src_mask */
364 0xffffffff, /* dst_mask */
365 false), /* pcrel_offset */
367 HOWTO (R_ARM_JUMP_SLOT, /* type */
369 2, /* size (0 = byte, 1 = short, 2 = long) */
371 false, /* pc_relative */
373 complain_overflow_bitfield,/* complain_on_overflow */
374 bfd_elf_generic_reloc, /* special_function */
375 "R_ARM_JUMP_SLOT", /* name */
376 true, /* partial_inplace */
377 0xffffffff, /* src_mask */
378 0xffffffff, /* dst_mask */
379 false), /* pcrel_offset */
381 HOWTO (R_ARM_RELATIVE, /* type */
383 2, /* size (0 = byte, 1 = short, 2 = long) */
385 false, /* pc_relative */
387 complain_overflow_bitfield,/* complain_on_overflow */
388 bfd_elf_generic_reloc, /* special_function */
389 "R_ARM_RELATIVE", /* name */
390 true, /* partial_inplace */
391 0xffffffff, /* src_mask */
392 0xffffffff, /* dst_mask */
393 false), /* pcrel_offset */
395 HOWTO (R_ARM_GOTOFF, /* type */
397 2, /* size (0 = byte, 1 = short, 2 = long) */
399 false, /* pc_relative */
401 complain_overflow_bitfield,/* complain_on_overflow */
402 bfd_elf_generic_reloc, /* special_function */
403 "R_ARM_GOTOFF", /* name */
404 true, /* partial_inplace */
405 0xffffffff, /* src_mask */
406 0xffffffff, /* dst_mask */
407 false), /* pcrel_offset */
409 HOWTO (R_ARM_GOTPC, /* type */
411 2, /* size (0 = byte, 1 = short, 2 = long) */
413 true, /* pc_relative */
415 complain_overflow_bitfield,/* complain_on_overflow */
416 bfd_elf_generic_reloc, /* special_function */
417 "R_ARM_GOTPC", /* name */
418 true, /* partial_inplace */
419 0xffffffff, /* src_mask */
420 0xffffffff, /* dst_mask */
421 true), /* pcrel_offset */
423 HOWTO (R_ARM_GOT32, /* type */
425 2, /* size (0 = byte, 1 = short, 2 = long) */
427 false, /* pc_relative */
429 complain_overflow_bitfield,/* complain_on_overflow */
430 bfd_elf_generic_reloc, /* special_function */
431 "R_ARM_GOT32", /* name */
432 true, /* partial_inplace */
433 0xffffffff, /* src_mask */
434 0xffffffff, /* dst_mask */
435 false), /* pcrel_offset */
437 HOWTO (R_ARM_PLT32, /* type */
439 2, /* size (0 = byte, 1 = short, 2 = long) */
441 true, /* pc_relative */
443 complain_overflow_bitfield,/* complain_on_overflow */
444 bfd_elf_generic_reloc, /* special_function */
445 "R_ARM_PLT32", /* name */
446 true, /* partial_inplace */
447 0x00ffffff, /* src_mask */
448 0x00ffffff, /* dst_mask */
449 true), /* pcrel_offset */
451 /* End of relocs used in ARM Linux */
453 HOWTO (R_ARM_RREL32, /* type */
455 0, /* size (0 = byte, 1 = short, 2 = long) */
457 false, /* pc_relative */
459 complain_overflow_dont,/* complain_on_overflow */
460 bfd_elf_generic_reloc, /* special_function */
461 "R_ARM_RREL32", /* name */
462 false, /* partial_inplace */
465 false), /* pcrel_offset */
467 HOWTO (R_ARM_RABS32, /* type */
469 0, /* size (0 = byte, 1 = short, 2 = long) */
471 false, /* pc_relative */
473 complain_overflow_dont,/* complain_on_overflow */
474 bfd_elf_generic_reloc, /* special_function */
475 "R_ARM_RABS32", /* name */
476 false, /* partial_inplace */
479 false), /* pcrel_offset */
481 HOWTO (R_ARM_RPC24, /* type */
483 0, /* size (0 = byte, 1 = short, 2 = long) */
485 false, /* pc_relative */
487 complain_overflow_dont,/* complain_on_overflow */
488 bfd_elf_generic_reloc, /* special_function */
489 "R_ARM_RPC24", /* name */
490 false, /* partial_inplace */
493 false), /* pcrel_offset */
495 HOWTO (R_ARM_RBASE, /* type */
497 0, /* size (0 = byte, 1 = short, 2 = long) */
499 false, /* pc_relative */
501 complain_overflow_dont,/* complain_on_overflow */
502 bfd_elf_generic_reloc, /* special_function */
503 "R_ARM_RBASE", /* name */
504 false, /* partial_inplace */
507 false), /* pcrel_offset */
511 /* GNU extension to record C++ vtable hierarchy */
512 static reloc_howto_type elf32_arm_vtinherit_howto =
513 HOWTO (R_ARM_GNU_VTINHERIT, /* type */
515 2, /* size (0 = byte, 1 = short, 2 = long) */
517 false, /* pc_relative */
519 complain_overflow_dont, /* complain_on_overflow */
520 NULL, /* special_function */
521 "R_ARM_GNU_VTINHERIT", /* name */
522 false, /* partial_inplace */
525 false); /* pcrel_offset */
527 /* GNU extension to record C++ vtable member usage */
528 static reloc_howto_type elf32_arm_vtentry_howto =
529 HOWTO (R_ARM_GNU_VTENTRY, /* type */
531 2, /* size (0 = byte, 1 = short, 2 = long) */
533 false, /* pc_relative */
535 complain_overflow_dont, /* complain_on_overflow */
536 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
537 "R_ARM_GNU_VTENTRY", /* name */
538 false, /* partial_inplace */
541 false); /* pcrel_offset */
543 /* 12 bit pc relative */
544 static reloc_howto_type elf32_arm_thm_pc11_howto =
545 HOWTO (R_ARM_THM_PC11, /* type */
547 1, /* size (0 = byte, 1 = short, 2 = long) */
549 true, /* pc_relative */
551 complain_overflow_signed, /* complain_on_overflow */
552 bfd_elf_generic_reloc, /* special_function */
553 "R_ARM_THM_PC11", /* name */
554 false, /* partial_inplace */
555 0x000007ff, /* src_mask */
556 0x000007ff, /* dst_mask */
557 true); /* pcrel_offset */
559 /* 12 bit pc relative */
560 static reloc_howto_type elf32_arm_thm_pc9_howto =
561 HOWTO (R_ARM_THM_PC9, /* type */
563 1, /* size (0 = byte, 1 = short, 2 = long) */
565 true, /* pc_relative */
567 complain_overflow_signed, /* complain_on_overflow */
568 bfd_elf_generic_reloc, /* special_function */
569 "R_ARM_THM_PC9", /* name */
570 false, /* partial_inplace */
571 0x000000ff, /* src_mask */
572 0x000000ff, /* dst_mask */
573 true); /* pcrel_offset */
577 elf32_arm_info_to_howto_rel (abfd, bfd_reloc, elf_reloc)
580 Elf32_Internal_Rel * elf_reloc;
584 r_type = ELF32_R_TYPE (elf_reloc->r_info);
588 case R_ARM_GNU_VTINHERIT:
589 bfd_reloc->howto = & elf32_arm_vtinherit_howto;
592 case R_ARM_GNU_VTENTRY:
593 bfd_reloc->howto = & elf32_arm_vtentry_howto;
597 bfd_reloc->howto = & elf32_arm_thm_pc11_howto;
601 bfd_reloc->howto = & elf32_arm_thm_pc9_howto;
605 if (r_type >= NUM_ELEM (elf32_arm_howto_table))
606 bfd_reloc->howto = NULL;
608 bfd_reloc->howto = & elf32_arm_howto_table[r_type];
613 struct elf32_arm_reloc_map
615 bfd_reloc_code_real_type bfd_reloc_val;
616 unsigned char elf_reloc_val;
619 static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
621 {BFD_RELOC_NONE, R_ARM_NONE},
622 {BFD_RELOC_ARM_PCREL_BRANCH, R_ARM_PC24},
623 {BFD_RELOC_32, R_ARM_ABS32},
624 {BFD_RELOC_32_PCREL, R_ARM_REL32},
625 {BFD_RELOC_8, R_ARM_ABS8},
626 {BFD_RELOC_16, R_ARM_ABS16},
627 {BFD_RELOC_ARM_OFFSET_IMM, R_ARM_ABS12},
628 {BFD_RELOC_ARM_THUMB_OFFSET, R_ARM_THM_ABS5},
629 {BFD_RELOC_THUMB_PCREL_BRANCH23, R_ARM_THM_PC22},
630 {BFD_RELOC_ARM_COPY, R_ARM_COPY},
631 {BFD_RELOC_ARM_GLOB_DAT, R_ARM_GLOB_DAT},
632 {BFD_RELOC_ARM_JUMP_SLOT, R_ARM_JUMP_SLOT},
633 {BFD_RELOC_ARM_RELATIVE, R_ARM_RELATIVE},
634 {BFD_RELOC_ARM_GOTOFF, R_ARM_GOTOFF},
635 {BFD_RELOC_ARM_GOTPC, R_ARM_GOTPC},
636 {BFD_RELOC_ARM_GOT32, R_ARM_GOT32},
637 {BFD_RELOC_ARM_PLT32, R_ARM_PLT32}
640 static reloc_howto_type *
641 elf32_arm_reloc_type_lookup (abfd, code)
643 bfd_reloc_code_real_type code;
649 case BFD_RELOC_VTABLE_INHERIT:
650 return & elf32_arm_vtinherit_howto;
652 case BFD_RELOC_VTABLE_ENTRY:
653 return & elf32_arm_vtentry_howto;
655 case BFD_RELOC_THUMB_PCREL_BRANCH12:
656 return & elf32_arm_thm_pc11_howto;
658 case BFD_RELOC_THUMB_PCREL_BRANCH9:
659 return & elf32_arm_thm_pc9_howto;
662 for (i = 0; i < NUM_ELEM (elf32_arm_reloc_map); i ++)
663 if (elf32_arm_reloc_map[i].bfd_reloc_val == code)
664 return & elf32_arm_howto_table[elf32_arm_reloc_map[i].elf_reloc_val];
670 #include "elf32-arm.h"