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
40 #define ARM_ELF_ABI_VERSION 0
41 #define ARM_ELF_OS_ABI_VERSION ELFOSABI_ARM
43 static reloc_howto_type
* elf32_arm_reloc_type_lookup
44 PARAMS ((bfd
* abfd
, bfd_reloc_code_real_type code
));
46 static reloc_howto_type elf32_arm_howto_table
[] =
49 HOWTO (R_ARM_NONE
, /* type */
51 0, /* size (0 = byte, 1 = short, 2 = long) */
53 false, /* pc_relative */
55 complain_overflow_dont
,/* complain_on_overflow */
56 bfd_elf_generic_reloc
, /* special_function */
57 "R_ARM_NONE", /* name */
58 false, /* partial_inplace */
61 false), /* pcrel_offset */
63 HOWTO (R_ARM_PC24
, /* type */
65 2, /* size (0 = byte, 1 = short, 2 = long) */
67 true, /* pc_relative */
69 complain_overflow_signed
,/* complain_on_overflow */
70 bfd_elf_generic_reloc
, /* special_function */
71 "R_ARM_PC24", /* name */
72 false, /* partial_inplace */
73 0x00ffffff, /* src_mask */
74 0x00ffffff, /* dst_mask */
75 true), /* pcrel_offset */
78 HOWTO (R_ARM_ABS32
, /* type */
80 2, /* size (0 = byte, 1 = short, 2 = long) */
82 false, /* pc_relative */
84 complain_overflow_bitfield
,/* complain_on_overflow */
85 bfd_elf_generic_reloc
, /* special_function */
86 "R_ARM_ABS32", /* name */
87 false, /* partial_inplace */
88 0xffffffff, /* src_mask */
89 0xffffffff, /* dst_mask */
90 false), /* pcrel_offset */
92 /* standard 32bit pc-relative reloc */
93 HOWTO (R_ARM_REL32
, /* type */
95 2, /* size (0 = byte, 1 = short, 2 = long) */
97 true, /* pc_relative */
99 complain_overflow_bitfield
,/* complain_on_overflow */
100 bfd_elf_generic_reloc
, /* special_function */
101 "R_ARM_REL32", /* name */
102 false, /* partial_inplace */
103 0xffffffff, /* src_mask */
104 0xffffffff, /* dst_mask */
105 true), /* pcrel_offset */
108 HOWTO (R_ARM_PC13
, /* type */
110 0, /* size (0 = byte, 1 = short, 2 = long) */
112 false, /* pc_relative */
114 complain_overflow_bitfield
,/* complain_on_overflow */
115 bfd_elf_generic_reloc
, /* special_function */
116 "R_ARM_PC13", /* name */
117 false, /* partial_inplace */
118 0x000000ff, /* src_mask */
119 0x000000ff, /* dst_mask */
120 false), /* pcrel_offset */
122 /* 16 bit absolute */
123 HOWTO (R_ARM_ABS16
, /* type */
125 1, /* size (0 = byte, 1 = short, 2 = long) */
127 false, /* pc_relative */
129 complain_overflow_bitfield
,/* complain_on_overflow */
130 bfd_elf_generic_reloc
, /* special_function */
131 "R_ARM_ABS16", /* name */
132 false, /* partial_inplace */
135 false), /* pcrel_offset */
137 /* 12 bit absolute */
138 HOWTO (R_ARM_ABS12
, /* type */
140 2, /* size (0 = byte, 1 = short, 2 = long) */
142 false, /* pc_relative */
144 complain_overflow_bitfield
,/* complain_on_overflow */
145 bfd_elf_generic_reloc
, /* special_function */
146 "R_ARM_ABS12", /* name */
147 false, /* partial_inplace */
148 0x000008ff, /* src_mask */
149 0x000008ff, /* dst_mask */
150 false), /* pcrel_offset */
152 HOWTO (R_ARM_THM_ABS5
, /* type */
154 1, /* size (0 = byte, 1 = short, 2 = long) */
156 false, /* pc_relative */
158 complain_overflow_bitfield
,/* complain_on_overflow */
159 bfd_elf_generic_reloc
, /* special_function */
160 "R_ARM_THM_ABS5", /* name */
161 false, /* partial_inplace */
162 0x000007e0, /* src_mask */
163 0x000007e0, /* dst_mask */
164 false), /* pcrel_offset */
167 HOWTO (R_ARM_ABS8
, /* type */
169 0, /* size (0 = byte, 1 = short, 2 = long) */
171 false, /* pc_relative */
173 complain_overflow_bitfield
,/* complain_on_overflow */
174 bfd_elf_generic_reloc
, /* special_function */
175 "R_ARM_ABS8", /* name */
176 false, /* partial_inplace */
177 0x000000ff, /* src_mask */
178 0x000000ff, /* dst_mask */
179 false), /* pcrel_offset */
181 HOWTO (R_ARM_SBREL32
, /* type */
183 0, /* size (0 = byte, 1 = short, 2 = long) */
185 false, /* pc_relative */
187 complain_overflow_dont
,/* complain_on_overflow */
188 bfd_elf_generic_reloc
, /* special_function */
189 "R_ARM_SBREL32", /* name */
190 false, /* partial_inplace */
193 false), /* pcrel_offset */
195 HOWTO (R_ARM_THM_PC22
, /* type */
197 2, /* size (0 = byte, 1 = short, 2 = long) */
199 true, /* pc_relative */
201 complain_overflow_signed
,/* complain_on_overflow */
202 bfd_elf_generic_reloc
, /* special_function */
203 "R_ARM_THM_PC22", /* name */
204 false, /* partial_inplace */
205 0x07ff07ff, /* src_mask */
206 0x07ff07ff, /* dst_mask */
207 true), /* pcrel_offset */
209 HOWTO (R_ARM_THM_PC8
, /* type */
211 1, /* size (0 = byte, 1 = short, 2 = long) */
213 true, /* pc_relative */
215 complain_overflow_signed
,/* complain_on_overflow */
216 bfd_elf_generic_reloc
, /* special_function */
217 "R_ARM_THM_PC8", /* name */
218 false, /* partial_inplace */
219 0x000000ff, /* src_mask */
220 0x000000ff, /* dst_mask */
221 true), /* pcrel_offset */
223 HOWTO (R_ARM_AMP_VCALL9
, /* type */
225 1, /* size (0 = byte, 1 = short, 2 = long) */
227 true, /* pc_relative */
229 complain_overflow_signed
,/* complain_on_overflow */
230 bfd_elf_generic_reloc
, /* special_function */
231 "R_ARM_AMP_VCALL9", /* name */
232 false, /* partial_inplace */
233 0x000000ff, /* src_mask */
234 0x000000ff, /* dst_mask */
235 true), /* pcrel_offset */
237 HOWTO (R_ARM_SWI24
, /* type */
239 0, /* size (0 = byte, 1 = short, 2 = long) */
241 false, /* pc_relative */
243 complain_overflow_signed
,/* complain_on_overflow */
244 bfd_elf_generic_reloc
, /* special_function */
245 "R_ARM_SWI24", /* name */
246 false, /* partial_inplace */
247 0x00000000, /* src_mask */
248 0x00000000, /* dst_mask */
249 false), /* pcrel_offset */
251 HOWTO (R_ARM_THM_SWI8
, /* type */
253 0, /* size (0 = byte, 1 = short, 2 = long) */
255 false, /* pc_relative */
257 complain_overflow_signed
,/* complain_on_overflow */
258 bfd_elf_generic_reloc
, /* special_function */
259 "R_ARM_SWI8", /* name */
260 false, /* partial_inplace */
261 0x00000000, /* src_mask */
262 0x00000000, /* dst_mask */
263 false), /* pcrel_offset */
265 /* These next two relocs are defined, but I do not know what they do. */
267 HOWTO (R_ARM_XPC25
, /* type */
269 0, /* size (0 = byte, 1 = short, 2 = long) */
271 false, /* pc_relative */
273 complain_overflow_signed
,/* complain_on_overflow */
274 bfd_elf_generic_reloc
, /* special_function */
275 "R_ARM_XPC25", /* name */
276 false, /* partial_inplace */
277 0x00000000, /* src_mask */
278 0x00000000, /* dst_mask */
279 false), /* pcrel_offset */
281 HOWTO (R_ARM_THM_XPC22
, /* type */
283 0, /* size (0 = byte, 1 = short, 2 = long) */
285 false, /* pc_relative */
287 complain_overflow_signed
,/* complain_on_overflow */
288 bfd_elf_generic_reloc
, /* special_function */
289 "R_ARM_THM_XPC22", /* name */
290 false, /* partial_inplace */
291 0x00000000, /* src_mask */
292 0x00000000, /* dst_mask */
293 false), /* pcrel_offset */
295 /* These next three relocs are not defined, but we need to fill the space. */
297 HOWTO (R_ARM_NONE
, /* type */
299 0, /* size (0 = byte, 1 = short, 2 = long) */
301 false, /* pc_relative */
303 complain_overflow_dont
,/* complain_on_overflow */
304 bfd_elf_generic_reloc
, /* special_function */
305 "R_ARM_unknown_17", /* name */
306 false, /* partial_inplace */
309 false), /* pcrel_offset */
311 HOWTO (R_ARM_NONE
, /* type */
313 0, /* size (0 = byte, 1 = short, 2 = long) */
315 false, /* pc_relative */
317 complain_overflow_dont
,/* complain_on_overflow */
318 bfd_elf_generic_reloc
, /* special_function */
319 "R_ARM_unknown_18", /* name */
320 false, /* partial_inplace */
323 false), /* pcrel_offset */
325 HOWTO (R_ARM_NONE
, /* type */
327 0, /* size (0 = byte, 1 = short, 2 = long) */
329 false, /* pc_relative */
331 complain_overflow_dont
,/* complain_on_overflow */
332 bfd_elf_generic_reloc
, /* special_function */
333 "R_ARM_unknown_19", /* name */
334 false, /* partial_inplace */
337 false), /* pcrel_offset */
339 /* Relocs used in ARM Linux */
341 HOWTO (R_ARM_COPY
, /* type */
343 2, /* size (0 = byte, 1 = short, 2 = long) */
345 false, /* pc_relative */
347 complain_overflow_bitfield
,/* complain_on_overflow */
348 bfd_elf_generic_reloc
, /* special_function */
349 "R_ARM_COPY", /* name */
350 true, /* partial_inplace */
351 0xffffffff, /* src_mask */
352 0xffffffff, /* dst_mask */
353 false), /* pcrel_offset */
355 HOWTO (R_ARM_GLOB_DAT
, /* type */
357 2, /* size (0 = byte, 1 = short, 2 = long) */
359 false, /* pc_relative */
361 complain_overflow_bitfield
,/* complain_on_overflow */
362 bfd_elf_generic_reloc
, /* special_function */
363 "R_ARM_GLOB_DAT", /* name */
364 true, /* partial_inplace */
365 0xffffffff, /* src_mask */
366 0xffffffff, /* dst_mask */
367 false), /* pcrel_offset */
369 HOWTO (R_ARM_JUMP_SLOT
, /* type */
371 2, /* size (0 = byte, 1 = short, 2 = long) */
373 false, /* pc_relative */
375 complain_overflow_bitfield
,/* complain_on_overflow */
376 bfd_elf_generic_reloc
, /* special_function */
377 "R_ARM_JUMP_SLOT", /* name */
378 true, /* partial_inplace */
379 0xffffffff, /* src_mask */
380 0xffffffff, /* dst_mask */
381 false), /* pcrel_offset */
383 HOWTO (R_ARM_RELATIVE
, /* type */
385 2, /* size (0 = byte, 1 = short, 2 = long) */
387 false, /* pc_relative */
389 complain_overflow_bitfield
,/* complain_on_overflow */
390 bfd_elf_generic_reloc
, /* special_function */
391 "R_ARM_RELATIVE", /* name */
392 true, /* partial_inplace */
393 0xffffffff, /* src_mask */
394 0xffffffff, /* dst_mask */
395 false), /* pcrel_offset */
397 HOWTO (R_ARM_GOTOFF
, /* type */
399 2, /* size (0 = byte, 1 = short, 2 = long) */
401 false, /* pc_relative */
403 complain_overflow_bitfield
,/* complain_on_overflow */
404 bfd_elf_generic_reloc
, /* special_function */
405 "R_ARM_GOTOFF", /* name */
406 true, /* partial_inplace */
407 0xffffffff, /* src_mask */
408 0xffffffff, /* dst_mask */
409 false), /* pcrel_offset */
411 HOWTO (R_ARM_GOTPC
, /* type */
413 2, /* size (0 = byte, 1 = short, 2 = long) */
415 true, /* pc_relative */
417 complain_overflow_bitfield
,/* complain_on_overflow */
418 bfd_elf_generic_reloc
, /* special_function */
419 "R_ARM_GOTPC", /* name */
420 true, /* partial_inplace */
421 0xffffffff, /* src_mask */
422 0xffffffff, /* dst_mask */
423 true), /* pcrel_offset */
425 HOWTO (R_ARM_GOT32
, /* type */
427 2, /* size (0 = byte, 1 = short, 2 = long) */
429 false, /* pc_relative */
431 complain_overflow_bitfield
,/* complain_on_overflow */
432 bfd_elf_generic_reloc
, /* special_function */
433 "R_ARM_GOT32", /* name */
434 true, /* partial_inplace */
435 0xffffffff, /* src_mask */
436 0xffffffff, /* dst_mask */
437 false), /* pcrel_offset */
439 HOWTO (R_ARM_PLT32
, /* type */
441 2, /* size (0 = byte, 1 = short, 2 = long) */
443 true, /* pc_relative */
445 complain_overflow_bitfield
,/* complain_on_overflow */
446 bfd_elf_generic_reloc
, /* special_function */
447 "R_ARM_PLT32", /* name */
448 true, /* partial_inplace */
449 0x00ffffff, /* src_mask */
450 0x00ffffff, /* dst_mask */
451 true), /* pcrel_offset */
453 /* End of relocs used in ARM Linux */
455 HOWTO (R_ARM_RREL32
, /* type */
457 0, /* size (0 = byte, 1 = short, 2 = long) */
459 false, /* pc_relative */
461 complain_overflow_dont
,/* complain_on_overflow */
462 bfd_elf_generic_reloc
, /* special_function */
463 "R_ARM_RREL32", /* name */
464 false, /* partial_inplace */
467 false), /* pcrel_offset */
469 HOWTO (R_ARM_RABS32
, /* type */
471 0, /* size (0 = byte, 1 = short, 2 = long) */
473 false, /* pc_relative */
475 complain_overflow_dont
,/* complain_on_overflow */
476 bfd_elf_generic_reloc
, /* special_function */
477 "R_ARM_RABS32", /* name */
478 false, /* partial_inplace */
481 false), /* pcrel_offset */
483 HOWTO (R_ARM_RPC24
, /* type */
485 0, /* size (0 = byte, 1 = short, 2 = long) */
487 false, /* pc_relative */
489 complain_overflow_dont
,/* complain_on_overflow */
490 bfd_elf_generic_reloc
, /* special_function */
491 "R_ARM_RPC24", /* name */
492 false, /* partial_inplace */
495 false), /* pcrel_offset */
497 HOWTO (R_ARM_RBASE
, /* type */
499 0, /* size (0 = byte, 1 = short, 2 = long) */
501 false, /* pc_relative */
503 complain_overflow_dont
,/* complain_on_overflow */
504 bfd_elf_generic_reloc
, /* special_function */
505 "R_ARM_RBASE", /* name */
506 false, /* partial_inplace */
509 false), /* pcrel_offset */
513 /* GNU extension to record C++ vtable hierarchy */
514 static reloc_howto_type elf32_arm_vtinherit_howto
=
515 HOWTO (R_ARM_GNU_VTINHERIT
, /* type */
517 2, /* size (0 = byte, 1 = short, 2 = long) */
519 false, /* pc_relative */
521 complain_overflow_dont
, /* complain_on_overflow */
522 NULL
, /* special_function */
523 "R_ARM_GNU_VTINHERIT", /* name */
524 false, /* partial_inplace */
527 false); /* pcrel_offset */
529 /* GNU extension to record C++ vtable member usage */
530 static reloc_howto_type elf32_arm_vtentry_howto
=
531 HOWTO (R_ARM_GNU_VTENTRY
, /* type */
533 2, /* size (0 = byte, 1 = short, 2 = long) */
535 false, /* pc_relative */
537 complain_overflow_dont
, /* complain_on_overflow */
538 _bfd_elf_rel_vtable_reloc_fn
, /* special_function */
539 "R_ARM_GNU_VTENTRY", /* name */
540 false, /* partial_inplace */
543 false); /* pcrel_offset */
545 /* 12 bit pc relative */
546 static reloc_howto_type elf32_arm_thm_pc11_howto
=
547 HOWTO (R_ARM_THM_PC11
, /* type */
549 1, /* size (0 = byte, 1 = short, 2 = long) */
551 true, /* pc_relative */
553 complain_overflow_signed
, /* complain_on_overflow */
554 bfd_elf_generic_reloc
, /* special_function */
555 "R_ARM_THM_PC11", /* name */
556 false, /* partial_inplace */
557 0x000007ff, /* src_mask */
558 0x000007ff, /* dst_mask */
559 true); /* pcrel_offset */
561 /* 12 bit pc relative */
562 static reloc_howto_type elf32_arm_thm_pc9_howto
=
563 HOWTO (R_ARM_THM_PC9
, /* type */
565 1, /* size (0 = byte, 1 = short, 2 = long) */
567 true, /* pc_relative */
569 complain_overflow_signed
, /* complain_on_overflow */
570 bfd_elf_generic_reloc
, /* special_function */
571 "R_ARM_THM_PC9", /* name */
572 false, /* partial_inplace */
573 0x000000ff, /* src_mask */
574 0x000000ff, /* dst_mask */
575 true); /* pcrel_offset */
579 elf32_arm_info_to_howto (abfd
, bfd_reloc
, elf_reloc
)
582 Elf32_Internal_Rel
* elf_reloc
;
586 r_type
= ELF32_R_TYPE (elf_reloc
->r_info
);
590 case R_ARM_GNU_VTINHERIT
:
591 bfd_reloc
->howto
= & elf32_arm_vtinherit_howto
;
594 case R_ARM_GNU_VTENTRY
:
595 bfd_reloc
->howto
= & elf32_arm_vtentry_howto
;
599 bfd_reloc
->howto
= & elf32_arm_thm_pc11_howto
;
603 bfd_reloc
->howto
= & elf32_arm_thm_pc9_howto
;
607 if (r_type
>= NUM_ELEM (elf32_arm_howto_table
))
608 bfd_reloc
->howto
= NULL
;
610 bfd_reloc
->howto
= & elf32_arm_howto_table
[r_type
];
615 struct elf32_arm_reloc_map
617 bfd_reloc_code_real_type bfd_reloc_val
;
618 unsigned char elf_reloc_val
;
621 static const struct elf32_arm_reloc_map elf32_arm_reloc_map
[] =
623 {BFD_RELOC_NONE
, R_ARM_NONE
},
624 {BFD_RELOC_ARM_PCREL_BRANCH
, R_ARM_PC24
},
625 {BFD_RELOC_32
, R_ARM_ABS32
},
626 {BFD_RELOC_32_PCREL
, R_ARM_REL32
},
627 {BFD_RELOC_8
, R_ARM_ABS8
},
628 {BFD_RELOC_16
, R_ARM_ABS16
},
629 {BFD_RELOC_ARM_OFFSET_IMM
, R_ARM_ABS12
},
630 {BFD_RELOC_ARM_THUMB_OFFSET
, R_ARM_THM_ABS5
},
631 {BFD_RELOC_THUMB_PCREL_BRANCH23
, R_ARM_THM_PC22
},
632 {BFD_RELOC_ARM_COPY
, R_ARM_COPY
},
633 {BFD_RELOC_ARM_GLOB_DAT
, R_ARM_GLOB_DAT
},
634 {BFD_RELOC_ARM_JUMP_SLOT
, R_ARM_JUMP_SLOT
},
635 {BFD_RELOC_ARM_RELATIVE
, R_ARM_RELATIVE
},
636 {BFD_RELOC_ARM_GOTOFF
, R_ARM_GOTOFF
},
637 {BFD_RELOC_ARM_GOTPC
, R_ARM_GOTPC
},
638 {BFD_RELOC_ARM_GOT32
, R_ARM_GOT32
},
639 {BFD_RELOC_ARM_PLT32
, R_ARM_PLT32
}
642 static reloc_howto_type
*
643 elf32_arm_reloc_type_lookup (abfd
, code
)
645 bfd_reloc_code_real_type code
;
651 case BFD_RELOC_VTABLE_INHERIT
:
652 return & elf32_arm_vtinherit_howto
;
654 case BFD_RELOC_VTABLE_ENTRY
:
655 return & elf32_arm_vtentry_howto
;
657 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
658 return & elf32_arm_thm_pc11_howto
;
660 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
661 return & elf32_arm_thm_pc9_howto
;
664 for (i
= 0; i
< NUM_ELEM (elf32_arm_reloc_map
); i
++)
665 if (elf32_arm_reloc_map
[i
].bfd_reloc_val
== code
)
666 return & elf32_arm_howto_table
[elf32_arm_reloc_map
[i
].elf_reloc_val
];
672 #include "elf32-arm.h"