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"