1 /* 32-bit ELF support for ARM
2 Copyright 1993, 1995, 1998 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 typedef unsigned long int insn32
;
28 typedef unsigned short int insn16
;
30 static reloc_howto_type
*elf32_arm_reloc_type_lookup
31 PARAMS ((bfd
* abfd
, bfd_reloc_code_real_type code
));
32 static void elf32_arm_info_to_howto
33 PARAMS ((bfd
*, arelent
*, Elf32_Internal_Rela
*));
34 static boolean elf32_arm_set_private_flags
35 PARAMS ((bfd
*, flagword
));
36 static boolean elf32_arm_copy_private_bfd_data
37 PARAMS ((bfd
*, bfd
*));
38 static boolean elf32_arm_merge_private_bfd_data
39 PARAMS ((bfd
*, bfd
*));
40 static boolean elf32_arm_print_private_bfd_data
41 PARAMS ((bfd
*, PTR
));
42 static int elf32_arm_get_symbol_type
43 PARAMS (( Elf_Internal_Sym
*));
44 static struct bfd_link_hash_table
*elf32_arm_link_hash_table_create
48 static insn32 insert_thumb_branch
49 PARAMS ((insn32
, int));
50 static struct elf_link_hash_entry
*find_thumb_glue
51 PARAMS ((struct bfd_link_info
*, CONST
char *, bfd
*));
52 static struct elf_link_hash_entry
*find_arm_glue
53 PARAMS ((struct bfd_link_info
*, CONST
char *, bfd
*));
54 static void record_arm_to_thumb_glue
55 PARAMS ((struct bfd_link_info
*, struct elf_link_hash_entry
*));
56 static void record_thumb_to_arm_glue
57 PARAMS ((struct bfd_link_info
*, struct elf_link_hash_entry
*));
59 /* The linker script knows the section names for placement.
60 The entry_names are used to do simple name mangling on the stubs.
61 Given a function name, and its type, the stub can be found. The
62 name can be changed. The only requirement is the %s be present.
65 #define INTERWORK_FLAG( abfd ) (elf_elfheader (abfd)->e_flags & EF_INTERWORK)
67 #define THUMB2ARM_GLUE_SECTION_NAME ".glue_7t"
68 #define THUMB2ARM_GLUE_ENTRY_NAME "__%s_from_thumb"
70 #define ARM2THUMB_GLUE_SECTION_NAME ".glue_7"
71 #define ARM2THUMB_GLUE_ENTRY_NAME "__%s_from_arm"
73 /* Get the ARM elf linker hash table from a link_info structure. */
74 #define elf32_arm_hash_table(info) \
75 ((struct elf32_arm_link_hash_table *) ((info)->hash))
77 /* ARM ELF linker hash table */
78 struct elf32_arm_link_hash_table
80 /* The main hash table. */
81 struct elf_link_hash_table root
;
83 /* The size in bytes of the section containg the Thumb-to-ARM glue. */
84 long int thumb_glue_size
;
86 /* The size in bytes of the section containg the ARM-to-Thumb glue. */
87 long int arm_glue_size
;
89 /* An arbitary input BFD chosen to hold the glue sections. */
90 bfd
*bfd_of_glue_owner
;
96 /* Create an ARM elf linker hash table */
98 static struct bfd_link_hash_table
*
99 elf32_arm_link_hash_table_create (abfd
)
102 struct elf32_arm_link_hash_table
*ret
;
104 ret
= ((struct elf32_arm_link_hash_table
*)
105 bfd_alloc (abfd
, sizeof (struct elf32_arm_link_hash_table
)));
106 if (ret
== (struct elf32_arm_link_hash_table
*) NULL
)
109 if (!_bfd_elf_link_hash_table_init (&ret
->root
, abfd
,
110 _bfd_elf_link_hash_newfunc
))
112 bfd_release (abfd
, ret
);
116 ret
->thumb_glue_size
= 0;
117 ret
->arm_glue_size
= 0;
118 ret
->bfd_of_glue_owner
= NULL
;
120 return &ret
->root
.root
;
123 static struct elf_link_hash_entry
*
124 find_thumb_glue (link_info
, name
, input_bfd
)
125 struct bfd_link_info
*link_info
;
130 struct elf_link_hash_entry
*hash
;
131 struct elf32_arm_link_hash_table
*hash_table
;
133 /* We need a pointer to the armelf specific hash table. */
134 hash_table
= elf32_arm_hash_table (link_info
);
138 bfd_malloc (strlen (name
) + strlen (THUMB2ARM_GLUE_ENTRY_NAME
) + 1));
140 BFD_ASSERT (tmp_name
);
142 sprintf (tmp_name
, THUMB2ARM_GLUE_ENTRY_NAME
, name
);
144 hash
= elf_link_hash_lookup
145 (&(hash_table
)->root
, tmp_name
, false, false, true);
148 /* xgettext:c-format */
149 _bfd_error_handler (_ ("%s: unable to find THUMB glue '%s' for `%s'"),
150 bfd_get_filename (input_bfd
), tmp_name
, name
);
157 static struct elf_link_hash_entry
*
158 find_arm_glue (link_info
, name
, input_bfd
)
159 struct bfd_link_info
*link_info
;
164 struct elf_link_hash_entry
*myh
;
165 struct elf32_arm_link_hash_table
*hash_table
;
167 /* We need a pointer to the elfarm specific hash table. */
168 hash_table
= elf32_arm_hash_table (link_info
);
171 bfd_malloc (strlen (name
) + strlen (ARM2THUMB_GLUE_ENTRY_NAME
) + 1));
173 BFD_ASSERT (tmp_name
);
175 sprintf (tmp_name
, ARM2THUMB_GLUE_ENTRY_NAME
, name
);
177 myh
= elf_link_hash_lookup
178 (&(hash_table
)->root
, tmp_name
, false, false, true);
181 /* xgettext:c-format */
182 _bfd_error_handler (_ ("%s: unable to find ARM glue '%s' for `%s'"),
183 bfd_get_filename (input_bfd
), tmp_name
, name
);
198 .word func @ behave as if you saw a ARM_32 reloc
201 #define ARM2THUMB_GLUE_SIZE 12
202 static const insn32 a2t1_ldr_insn
= 0xe59fc000;
203 static const insn32 a2t2_bx_r12_insn
= 0xe12fff1c;
204 static const insn32 a2t3_func_addr_insn
= 0x00000001;
207 Thumb->ARM: Thumb->(non-interworking aware) ARM
211 __func_from_thumb: __func_from_thumb:
213 nop ldr r6, __func_addr
215 __func_change_to_arm: bx r6
217 __func_back_to_thumb:
224 #define THUMB2ARM_GLUE_SIZE 8
225 static const insn16 t2a1_bx_pc_insn
= 0x4778;
226 static const insn16 t2a2_noop_insn
= 0x46c0;
227 static const insn32 t2a3_b_insn
= 0xea000000;
229 static const insn16 t2a1_push_insn
= 0xb540;
230 static const insn16 t2a2_ldr_insn
= 0x4e03;
231 static const insn16 t2a3_mov_insn
= 0x46fe;
232 static const insn16 t2a4_bx_insn
= 0x4730;
233 static const insn32 t2a5_pop_insn
= 0xe8bd4040;
234 static const insn32 t2a6_bx_insn
= 0xe12fff1e;
237 bfd_elf32_arm_allocate_interworking_sections (info
)
238 struct bfd_link_info
*info
;
242 struct elf32_arm_link_hash_table
*globals
;
244 globals
= elf32_arm_hash_table (info
);
246 BFD_ASSERT (globals
!= NULL
);
248 if (globals
->arm_glue_size
!= 0)
250 BFD_ASSERT (globals
->bfd_of_glue_owner
!= NULL
);
252 s
= bfd_get_section_by_name
253 (globals
->bfd_of_glue_owner
, ARM2THUMB_GLUE_SECTION_NAME
);
255 BFD_ASSERT (s
!= NULL
);
257 foo
= (bfd_byte
*) bfd_alloc
258 (globals
->bfd_of_glue_owner
, globals
->arm_glue_size
);
260 s
->_raw_size
= s
->_cooked_size
= globals
->arm_glue_size
;
264 if (globals
->thumb_glue_size
!= 0)
266 BFD_ASSERT (globals
->bfd_of_glue_owner
!= NULL
);
268 s
= bfd_get_section_by_name
269 (globals
->bfd_of_glue_owner
, THUMB2ARM_GLUE_SECTION_NAME
);
271 BFD_ASSERT (s
!= NULL
);
273 foo
= (bfd_byte
*) bfd_alloc
274 (globals
->bfd_of_glue_owner
, globals
->thumb_glue_size
);
276 s
->_raw_size
= s
->_cooked_size
= globals
->thumb_glue_size
;
284 record_arm_to_thumb_glue (link_info
, h
)
285 struct bfd_link_info
*link_info
;
286 struct elf_link_hash_entry
*h
;
288 const char *name
= h
->root
.root
.string
;
289 register asection
*s
;
291 struct elf_link_hash_entry
*myh
;
292 struct elf32_arm_link_hash_table
*globals
;
294 globals
= elf32_arm_hash_table (link_info
);
296 BFD_ASSERT (globals
!= NULL
);
297 BFD_ASSERT (globals
->bfd_of_glue_owner
!= NULL
);
299 s
= bfd_get_section_by_name
300 (globals
->bfd_of_glue_owner
, ARM2THUMB_GLUE_SECTION_NAME
);
303 BFD_ASSERT (s
!= NULL
);
306 bfd_malloc (strlen (name
) + strlen (ARM2THUMB_GLUE_ENTRY_NAME
) + 1));
308 BFD_ASSERT (tmp_name
);
310 sprintf (tmp_name
, ARM2THUMB_GLUE_ENTRY_NAME
, name
);
312 myh
= elf_link_hash_lookup
313 (&(globals
)->root
, tmp_name
, false, false, true);
318 return; /* we've already seen this guy */
321 /* The only trick here is using hash_table->arm_glue_size as the value. Even
322 though the section isn't allocated yet, this is where we will be putting
325 _bfd_generic_link_add_one_symbol (link_info
, globals
->bfd_of_glue_owner
, tmp_name
,
327 s
, globals
->arm_glue_size
+ 1,
329 (struct bfd_link_hash_entry
**) &myh
);
333 globals
->arm_glue_size
+= ARM2THUMB_GLUE_SIZE
;
339 record_thumb_to_arm_glue (link_info
, h
)
340 struct bfd_link_info
*link_info
;
341 struct elf_link_hash_entry
*h
;
343 const char *name
= h
->root
.root
.string
;
344 register asection
*s
;
346 struct elf_link_hash_entry
*myh
;
347 struct elf32_arm_link_hash_table
*hash_table
;
350 hash_table
= elf32_arm_hash_table (link_info
);
352 BFD_ASSERT (hash_table
!= NULL
);
353 BFD_ASSERT (hash_table
->bfd_of_glue_owner
!= NULL
);
355 s
= bfd_get_section_by_name
356 (hash_table
->bfd_of_glue_owner
, THUMB2ARM_GLUE_SECTION_NAME
);
358 BFD_ASSERT (s
!= NULL
);
360 tmp_name
= (char *) bfd_malloc (strlen (name
) + strlen (THUMB2ARM_GLUE_ENTRY_NAME
) + 1);
362 BFD_ASSERT (tmp_name
);
364 sprintf (tmp_name
, THUMB2ARM_GLUE_ENTRY_NAME
, name
);
366 myh
= elf_link_hash_lookup
367 (&(hash_table
)->root
, tmp_name
, false, false, true);
372 return; /* we've already seen this guy */
375 _bfd_generic_link_add_one_symbol (link_info
, hash_table
->bfd_of_glue_owner
, tmp_name
,
376 BSF_GLOBAL
, s
, hash_table
->thumb_glue_size
+ 1,
378 (struct bfd_link_hash_entry
**) &myh
);
380 /* If we mark it 'thumb', the disassembler will do a better job. */
381 bind
= ELF_ST_BIND (myh
->type
);
382 myh
->type
= ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
386 /* Allocate another symbol to mark where we switch to arm mode. */
388 #define CHANGE_TO_ARM "__%s_change_to_arm"
389 #define BACK_FROM_ARM "__%s_back_from_arm"
391 tmp_name
= (char *) bfd_malloc (strlen (name
) + strlen (CHANGE_TO_ARM
) + 1);
393 BFD_ASSERT (tmp_name
);
395 sprintf (tmp_name
, CHANGE_TO_ARM
, name
);
399 _bfd_generic_link_add_one_symbol (link_info
, hash_table
->bfd_of_glue_owner
, tmp_name
,
400 BSF_LOCAL
, s
, hash_table
->thumb_glue_size
+ 4,
402 (struct bfd_link_hash_entry
**) &myh
);
406 hash_table
->thumb_glue_size
+= THUMB2ARM_GLUE_SIZE
;
411 /* Select a BFD to be used to hold the sections used by the glue code.
412 This function is called from the linker scripts in ld/emultempl/
415 bfd_elf32_arm_get_bfd_for_interworking (abfd
, info
)
417 struct bfd_link_info
*info
;
419 struct elf32_arm_link_hash_table
*globals
;
423 /* If we are only performing a partial link do not bother
424 getting a bfd to hold the glue. */
425 if (info
->relocateable
)
428 globals
= elf32_arm_hash_table (info
);
430 BFD_ASSERT (globals
!= NULL
);
432 if (globals
->bfd_of_glue_owner
!= NULL
)
435 sec
= bfd_get_section_by_name (abfd
, ARM2THUMB_GLUE_SECTION_NAME
);
439 flags
= SEC_ALLOC
| SEC_LOAD
| SEC_HAS_CONTENTS
| SEC_IN_MEMORY
;
441 sec
= bfd_make_section (abfd
, ARM2THUMB_GLUE_SECTION_NAME
);
444 || !bfd_set_section_flags (abfd
, sec
, flags
)
445 || !bfd_set_section_alignment (abfd
, sec
, 2))
449 sec
= bfd_get_section_by_name (abfd
, THUMB2ARM_GLUE_SECTION_NAME
);
453 flags
= SEC_ALLOC
| SEC_LOAD
| SEC_HAS_CONTENTS
| SEC_IN_MEMORY
;
455 sec
= bfd_make_section (abfd
, THUMB2ARM_GLUE_SECTION_NAME
);
458 || !bfd_set_section_flags (abfd
, sec
, flags
)
459 || !bfd_set_section_alignment (abfd
, sec
, 2))
463 /* Save the bfd for later use. */
464 globals
->bfd_of_glue_owner
= abfd
;
470 bfd_elf32_arm_process_before_allocation (abfd
, link_info
)
472 struct bfd_link_info
*link_info
;
474 Elf_Internal_Shdr
*symtab_hdr
;
475 Elf_Internal_Rela
*free_relocs
= NULL
;
476 Elf_Internal_Rela
*irel
, *irelend
;
477 bfd_byte
*contents
= NULL
;
478 bfd_byte
*free_contents
= NULL
;
479 Elf32_External_Sym
*extsyms
= NULL
;
480 Elf32_External_Sym
*free_extsyms
= NULL
;
483 struct elf32_arm_link_hash_table
*globals
;
485 /* If we are only performing a partial link do not bother
486 to construct any glue. */
487 if (link_info
->relocateable
)
490 /* Here we have a bfd that is to be included on the link. We have a hook
491 to do reloc rummaging, before section sizes are nailed down. */
493 globals
= elf32_arm_hash_table (link_info
);
495 BFD_ASSERT (globals
!= NULL
);
496 BFD_ASSERT (globals
->bfd_of_glue_owner
!= NULL
);
498 /* Rummage around all the relocs and map the glue vectors. */
499 sec
= abfd
->sections
;
504 for (; sec
!= NULL
; sec
= sec
->next
)
507 if (sec
->reloc_count
== 0)
510 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
511 /* Load the relocs. */
513 irel
= (_bfd_elf32_link_read_relocs (abfd
, sec
, (PTR
) NULL
,
514 (Elf_Internal_Rela
*) NULL
, false));
516 BFD_ASSERT (irel
!= 0);
518 irelend
= irel
+ sec
->reloc_count
;
519 for (; irel
< irelend
; irel
++)
522 unsigned long r_index
;
525 struct elf_link_hash_entry
*h
;
527 r_type
= ELF32_R_TYPE (irel
->r_info
);
528 r_index
= ELF32_R_SYM (irel
->r_info
);
530 /* These are the only relocation types we care about */
531 if (r_type
!= R_ARM_PC24
532 && r_type
!= R_ARM_THM_PC22
)
535 /* Get the section contents if we haven't done so already. */
536 if (contents
== NULL
)
538 /* Get cached copy if it exists. */
539 if (elf_section_data (sec
)->this_hdr
.contents
!= NULL
)
540 contents
= elf_section_data (sec
)->this_hdr
.contents
;
543 /* Go get them off disk. */
544 contents
= (bfd_byte
*) bfd_malloc (sec
->_raw_size
);
545 if (contents
== NULL
)
547 free_contents
= contents
;
549 if (!bfd_get_section_contents (abfd
, sec
, contents
,
550 (file_ptr
) 0, sec
->_raw_size
))
555 /* Read this BFD's symbols if we haven't done so already. */
558 /* Get cached copy if it exists. */
559 if (symtab_hdr
->contents
!= NULL
)
560 extsyms
= (Elf32_External_Sym
*) symtab_hdr
->contents
;
563 /* Go get them off disk. */
564 extsyms
= ((Elf32_External_Sym
*)
565 bfd_malloc (symtab_hdr
->sh_size
));
568 free_extsyms
= extsyms
;
569 if (bfd_seek (abfd
, symtab_hdr
->sh_offset
, SEEK_SET
) != 0
570 || (bfd_read (extsyms
, 1, symtab_hdr
->sh_size
, abfd
)
571 != symtab_hdr
->sh_size
))
576 /* If the relocation is not against a symbol it cannot concern us. */
580 /* We don't care about local symbols */
581 if (r_index
< symtab_hdr
->sh_info
)
584 /* This is an external symbol */
585 r_index
-= symtab_hdr
->sh_info
;
586 h
= (struct elf_link_hash_entry
*)
587 elf_sym_hashes (abfd
)[r_index
];
589 /* If the relocation is against a static symbol it must be within
590 the current section and so cannot be a cross ARM/Thumb relocation. */
597 /* This one is a call from arm code. We need to look up
598 the target of the call. If it is a thumb target, we
601 if (ELF_ST_TYPE(h
->type
) == STT_ARM_TFUNC
)
602 record_arm_to_thumb_glue (link_info
, h
);
607 /* This one is a call from thumb code. We look
608 up the target of the call. If it is not a thumb
609 target, we insert glue. */
611 if (ELF_ST_TYPE (h
->type
) != STT_ARM_TFUNC
)
612 record_thumb_to_arm_glue (link_info
, h
);
623 if (free_relocs
!= NULL
)
625 if (free_contents
!= NULL
)
626 free (free_contents
);
627 if (free_extsyms
!= NULL
)
634 #define TARGET_UNDERSCORE '_'
636 static reloc_howto_type elf32_arm_howto_table
[] =
639 HOWTO (R_ARM_NONE
, /* type */
641 0, /* size (0 = byte, 1 = short, 2 = long) */
643 false, /* pc_relative */
645 complain_overflow_dont
, /* complain_on_overflow */
646 bfd_elf_generic_reloc
, /* special_function */
647 "R_ARM_NONE", /* name */
648 false, /* partial_inplace */
651 false), /* pcrel_offset */
653 HOWTO (R_ARM_PC24
, /* type */
655 2, /* size (0 = byte, 1 = short, 2 = long) */
657 true, /* pc_relative */
659 complain_overflow_signed
, /* complain_on_overflow */
660 bfd_elf_generic_reloc
, /* special_function */
661 "R_ARM_PC24", /* name */
662 false, /* partial_inplace */
663 0x00ffffff, /* src_mask */
664 0x00ffffff, /* dst_mask */
665 true), /* pcrel_offset */
667 /* 32 bit absolute */
668 HOWTO (R_ARM_ABS32
, /* type */
670 2, /* size (0 = byte, 1 = short, 2 = long) */
672 false, /* pc_relative */
674 complain_overflow_bitfield
, /* complain_on_overflow */
675 bfd_elf_generic_reloc
, /* special_function */
676 "R_ARM_ABS32", /* name */
677 false, /* partial_inplace */
678 0xffffffff, /* src_mask */
679 0xffffffff, /* dst_mask */
680 false), /* pcrel_offset */
682 /* standard 32bit pc-relative reloc */
683 HOWTO (R_ARM_REL32
, /* type */
685 2, /* size (0 = byte, 1 = short, 2 = long) */
687 true, /* pc_relative */
689 complain_overflow_bitfield
, /* complain_on_overflow */
690 bfd_elf_generic_reloc
, /* special_function */
691 "R_ARM_REL32", /* name */
692 false, /* partial_inplace */
693 0xffffffff, /* src_mask */
694 0xffffffff, /* dst_mask */
695 true), /* pcrel_offset */
698 HOWTO (R_ARM_ABS8
, /* type */
700 0, /* size (0 = byte, 1 = short, 2 = long) */
702 false, /* pc_relative */
704 complain_overflow_bitfield
, /* complain_on_overflow */
705 bfd_elf_generic_reloc
, /* special_function */
706 "R_ARM_ABS8", /* name */
707 false, /* partial_inplace */
708 0x000000ff, /* src_mask */
709 0x000000ff, /* dst_mask */
710 false), /* pcrel_offset */
712 /* 16 bit absolute */
713 HOWTO (R_ARM_ABS16
, /* type */
715 1, /* size (0 = byte, 1 = short, 2 = long) */
717 false, /* pc_relative */
719 complain_overflow_bitfield
, /* complain_on_overflow */
720 bfd_elf_generic_reloc
, /* special_function */
721 "R_ARM_ABS16", /* name */
722 false, /* partial_inplace */
725 false), /* pcrel_offset */
727 /* 12 bit absolute */
728 HOWTO (R_ARM_ABS12
, /* type */
730 2, /* size (0 = byte, 1 = short, 2 = long) */
732 false, /* pc_relative */
734 complain_overflow_bitfield
, /* complain_on_overflow */
735 bfd_elf_generic_reloc
, /* special_function */
736 "R_ARM_ABS12", /* name */
737 false, /* partial_inplace */
738 0x000008ff, /* src_mask */
739 0x000008ff, /* dst_mask */
740 false), /* pcrel_offset */
742 HOWTO (R_ARM_THM_ABS5
, /* type */
744 2, /* size (0 = byte, 1 = short, 2 = long) */
746 false, /* pc_relative */
748 complain_overflow_bitfield
, /* complain_on_overflow */
749 bfd_elf_generic_reloc
, /* special_function */
750 "R_ARM_THM_ABS5", /* name */
751 false, /* partial_inplace */
752 0x000007e0, /* src_mask */
753 0x000007e0, /* dst_mask */
754 false), /* pcrel_offset */
756 HOWTO (R_ARM_THM_PC22
, /* type */
758 2, /* size (0 = byte, 1 = short, 2 = long) */
760 true, /* pc_relative */
762 complain_overflow_signed
, /* complain_on_overflow */
763 bfd_elf_generic_reloc
, /* special_function */
764 "R_ARM_THM_PC22", /* name */
765 false, /* partial_inplace */
766 0x07ff07ff, /* src_mask */
767 0x07ff07ff, /* dst_mask */
768 true), /* pcrel_offset */
770 HOWTO (R_ARM_SBREL32
, /* type */
772 0, /* size (0 = byte, 1 = short, 2 = long) */
774 false, /* pc_relative */
776 complain_overflow_dont
, /* complain_on_overflow */
777 bfd_elf_generic_reloc
, /* special_function */
778 "R_ARM_SBREL32", /* name */
779 false, /* partial_inplace */
782 false), /* pcrel_offset */
784 HOWTO (R_ARM_AMP_VCALL9
, /* type */
786 1, /* size (0 = byte, 1 = short, 2 = long) */
788 true, /* pc_relative */
790 complain_overflow_signed
, /* complain_on_overflow */
791 bfd_elf_generic_reloc
, /* special_function */
792 "R_ARM_AMP_VCALL9", /* name */
793 false, /* partial_inplace */
794 0x000000ff, /* src_mask */
795 0x000000ff, /* dst_mask */
796 true), /* pcrel_offset */
798 /* 12 bit pc relative */
799 HOWTO (R_ARM_THM_PC11
, /* type */
801 1, /* size (0 = byte, 1 = short, 2 = long) */
803 true, /* pc_relative */
805 complain_overflow_signed
, /* complain_on_overflow */
806 bfd_elf_generic_reloc
, /* special_function */
807 "R_ARM_THM_PC11", /* name */
808 false, /* partial_inplace */
809 0x000007ff, /* src_mask */
810 0x000007ff, /* dst_mask */
811 true), /* pcrel_offset */
813 /* 12 bit pc relative */
814 HOWTO (R_ARM_THM_PC9
, /* type */
816 1, /* size (0 = byte, 1 = short, 2 = long) */
818 true, /* pc_relative */
820 complain_overflow_signed
, /* complain_on_overflow */
821 bfd_elf_generic_reloc
, /* special_function */
822 "R_ARM_THM_PC9", /* name */
823 false, /* partial_inplace */
824 0x000000ff, /* src_mask */
825 0x000000ff, /* dst_mask */
826 true), /* pcrel_offset */
828 /* FILL ME IN (#13-249) */
831 HOWTO (R_ARM_RREL32
, /* type */
833 0, /* size (0 = byte, 1 = short, 2 = long) */
835 false, /* pc_relative */
837 complain_overflow_dont
, /* complain_on_overflow */
838 bfd_elf_generic_reloc
, /* special_function */
839 "R_ARM_RREL32", /* name */
840 false, /* partial_inplace */
843 false), /* pcrel_offset */
845 HOWTO (R_ARM_RABS32
, /* type */
847 0, /* size (0 = byte, 1 = short, 2 = long) */
849 false, /* pc_relative */
851 complain_overflow_dont
, /* complain_on_overflow */
852 bfd_elf_generic_reloc
, /* special_function */
853 "R_ARM_RABS32", /* name */
854 false, /* partial_inplace */
857 false), /* pcrel_offset */
859 HOWTO (R_ARM_RPC24
, /* type */
861 0, /* size (0 = byte, 1 = short, 2 = long) */
863 false, /* pc_relative */
865 complain_overflow_dont
, /* complain_on_overflow */
866 bfd_elf_generic_reloc
, /* special_function */
867 "R_ARM_RPC24", /* name */
868 false, /* partial_inplace */
871 false), /* pcrel_offset */
873 HOWTO (R_ARM_RBASE
, /* type */
875 0, /* size (0 = byte, 1 = short, 2 = long) */
877 false, /* pc_relative */
879 complain_overflow_dont
, /* complain_on_overflow */
880 bfd_elf_generic_reloc
, /* special_function */
881 "R_ARM_RBASE", /* name */
882 false, /* partial_inplace */
885 false), /* pcrel_offset */
888 struct elf32_arm_reloc_map
890 unsigned char bfd_reloc_val
;
891 unsigned char elf_reloc_val
;
894 static const struct elf32_arm_reloc_map elf32_arm_reloc_map
[] =
896 {BFD_RELOC_NONE
, R_ARM_NONE
,},
897 {BFD_RELOC_ARM_PCREL_BRANCH
, R_ARM_PC24
,},
898 {BFD_RELOC_32
, R_ARM_ABS32
,},
899 {BFD_RELOC_32_PCREL
, R_ARM_REL32
,},
900 {BFD_RELOC_8
, R_ARM_ABS8
,},
901 {BFD_RELOC_16
, R_ARM_ABS16
,},
902 {BFD_RELOC_ARM_OFFSET_IMM
, R_ARM_ABS12
,},
903 {BFD_RELOC_ARM_THUMB_OFFSET
, R_ARM_THM_ABS5
,},
904 {BFD_RELOC_THUMB_PCREL_BRANCH23
, R_ARM_THM_PC22
,},
905 {BFD_RELOC_NONE
, R_ARM_SBREL32
,},
906 {BFD_RELOC_NONE
, R_ARM_AMP_VCALL9
,},
907 {BFD_RELOC_THUMB_PCREL_BRANCH12
, R_ARM_THM_PC11
,},
908 {BFD_RELOC_THUMB_PCREL_BRANCH9
, R_ARM_THM_PC9
,}
911 static reloc_howto_type
*
912 elf32_arm_reloc_type_lookup (abfd
, code
)
914 bfd_reloc_code_real_type code
;
919 i
< sizeof (elf32_arm_reloc_map
) / sizeof (struct elf32_arm_reloc_map
);
922 if (elf32_arm_reloc_map
[i
].bfd_reloc_val
== code
)
923 return &elf32_arm_howto_table
[elf32_arm_reloc_map
[i
].elf_reloc_val
];
930 elf32_arm_info_to_howto (abfd
, bfd_reloc
, elf_reloc
)
933 Elf32_Internal_Rela
*elf_reloc
;
937 r_type
= ELF32_R_TYPE (elf_reloc
->r_info
);
938 /* fixme: need range test */
939 /* BFD_ASSERT (r_type < (unsigned int) R_ELF32_ARM_MAX); */
940 bfd_reloc
->howto
= &elf32_arm_howto_table
[r_type
];
943 /* The thumb form of a long branch is a bit finicky, because the offset
944 encoding is split over two fields, each in it's own instruction. They
945 can occur in any order. So given a thumb form of long branch, and an
946 offset, insert the offset into the thumb branch and return finished
949 It takes two thumb instructions to encode the target address. Each has
950 11 bits to invest. The upper 11 bits are stored in one (identifed by
951 H-0.. see below), the lower 11 bits are stored in the other (identified
954 Combine together and shifted left by 1 (it's a half word address) and
958 H-0, upper address-0 = 000
960 H-1, lower address-0 = 800
962 They can be ordered either way, but the arm tools I've seen always put
963 the lower one first. It probably doesn't matter. krk@cygnus.com
965 XXX: Actually the order does matter. The second instruction (H-1)
966 moves the computed address into the PC, so it must be the second one
967 in the sequence. The problem, however is that whilst little endian code
968 stores the instructions in HI then LOW order, big endian code does the
969 reverse. nickc@cygnus.com */
971 #define LOW_HI_ORDER 0xF800F000
972 #define HI_LOW_ORDER 0xF000F800
975 insert_thumb_branch (br_insn
, rel_off
)
979 unsigned int low_bits
;
980 unsigned int high_bits
;
983 BFD_ASSERT ((rel_off
& 1) != 1);
985 rel_off
>>= 1; /* half word aligned address */
986 low_bits
= rel_off
& 0x000007FF; /* the bottom 11 bits */
987 high_bits
= (rel_off
>> 11) & 0x000007FF; /* the top 11 bits */
989 if ((br_insn
& LOW_HI_ORDER
) == LOW_HI_ORDER
)
990 br_insn
= LOW_HI_ORDER
| (low_bits
<< 16) | high_bits
;
991 else if ((br_insn
& HI_LOW_ORDER
) == HI_LOW_ORDER
)
992 br_insn
= HI_LOW_ORDER
| (high_bits
<< 16) | low_bits
;
994 abort (); /* error - not a valid branch instruction form */
996 /* FIXME: abort is probably not the right call. krk@cygnus.com */
1001 /* Thumb code calling an ARM function */
1003 elf32_thumb_to_arm_stub (info
, name
, input_bfd
, output_bfd
, input_section
,
1004 hit_data
, sym_sec
, offset
, addend
, val
)
1005 struct bfd_link_info
*info
;
1009 asection
*input_section
;
1018 unsigned long int tmp
;
1019 long int ret_offset
;
1020 struct elf_link_hash_entry
*myh
;
1021 struct elf32_arm_link_hash_table
*globals
;
1023 myh
= find_thumb_glue (info
, name
, input_bfd
);
1027 globals
= elf32_arm_hash_table (info
);
1029 BFD_ASSERT (globals
!= NULL
);
1030 BFD_ASSERT (globals
->bfd_of_glue_owner
!= NULL
);
1032 my_offset
= myh
->root
.u
.def
.value
;
1034 s
= bfd_get_section_by_name (globals
->bfd_of_glue_owner
,
1035 THUMB2ARM_GLUE_SECTION_NAME
);
1037 BFD_ASSERT (s
!= NULL
);
1038 BFD_ASSERT (s
->contents
!= NULL
);
1039 BFD_ASSERT (s
->output_section
!= NULL
);
1041 if ((my_offset
& 0x01) == 0x01)
1044 && sym_sec
->owner
!= NULL
1045 && !INTERWORK_FLAG (sym_sec
->owner
))
1048 (_ ("%s(%s): warning: interworking not enabled."),
1049 bfd_get_filename (sym_sec
->owner
), name
);
1051 (_ (" first occurrence: %s: thumb call to arm"),
1052 bfd_get_filename (input_bfd
));
1056 myh
->root
.u
.def
.value
= my_offset
;
1058 bfd_put_16 (output_bfd
, t2a1_bx_pc_insn
,
1059 s
->contents
+ my_offset
);
1061 bfd_put_16 (output_bfd
, t2a2_noop_insn
,
1062 s
->contents
+ my_offset
+ 2);
1065 ((bfd_signed_vma
) val
) /* Address of destination of the stub */
1067 (s
->output_offset
/* Offset from the start of the current section to the start of the stubs. */
1068 + my_offset
/* Offset of the start of this stub from the start of the stubs. */
1069 + s
->output_section
->vma
) /* Address of the start of the current section. */
1070 + 4 /* The branch instruction is 4 bytes into the stub. */
1071 + 8); /* ARM branches work from the pc of the instruction + 8. */
1073 bfd_put_32 (output_bfd
,
1074 t2a3_b_insn
| ((ret_offset
>> 2) & 0x00FFFFFF),
1075 s
->contents
+ my_offset
+ 4);
1078 BFD_ASSERT (my_offset
<= globals
->thumb_glue_size
);
1080 /* Now go back and fix up the original BL insn to point
1085 - (input_section
->output_offset
1089 tmp
= bfd_get_32 (input_bfd
, hit_data
1090 - input_section
->vma
);
1092 bfd_put_32 (output_bfd
,
1093 insert_thumb_branch (tmp
, ret_offset
),
1094 hit_data
- input_section
->vma
);
1097 /* Arm code calling a Thumb function */
1099 elf32_arm_to_thumb_stub (info
, name
, input_bfd
, output_bfd
, input_section
,
1100 hit_data
, sym_sec
, offset
, addend
, val
)
1102 struct bfd_link_info
*info
;
1106 asection
*input_section
;
1113 unsigned long int tmp
;
1116 long int ret_offset
;
1117 struct elf_link_hash_entry
*myh
;
1118 struct elf32_arm_link_hash_table
*globals
;
1120 myh
= find_arm_glue (info
, name
, input_bfd
);
1124 globals
= elf32_arm_hash_table (info
);
1126 BFD_ASSERT (globals
!= NULL
);
1127 BFD_ASSERT (globals
->bfd_of_glue_owner
!= NULL
);
1129 my_offset
= myh
->root
.u
.def
.value
;
1130 s
= bfd_get_section_by_name (globals
->bfd_of_glue_owner
,
1131 ARM2THUMB_GLUE_SECTION_NAME
);
1132 BFD_ASSERT (s
!= NULL
);
1133 BFD_ASSERT (s
->contents
!= NULL
);
1134 BFD_ASSERT (s
->output_section
!= NULL
);
1136 if ((my_offset
& 0x01) == 0x01)
1139 && sym_sec
->owner
!= NULL
1140 && !INTERWORK_FLAG (sym_sec
->owner
))
1143 (_ ("%s(%s): warning: interworking not enabled."),
1144 bfd_get_filename (sym_sec
->owner
), name
);
1146 (_ (" first occurrence: %s: arm call to thumb"),
1147 bfd_get_filename (input_bfd
));
1150 myh
->root
.u
.def
.value
= my_offset
;
1152 bfd_put_32 (output_bfd
, a2t1_ldr_insn
,
1153 s
->contents
+ my_offset
);
1155 bfd_put_32 (output_bfd
, a2t2_bx_r12_insn
,
1156 s
->contents
+ my_offset
+ 4);
1158 /* It's a thumb address. Add the low order bit. */
1159 bfd_put_32 (output_bfd
, val
| a2t3_func_addr_insn
,
1160 s
->contents
+ my_offset
+ 8);
1163 BFD_ASSERT (my_offset
<= globals
->arm_glue_size
);
1165 tmp
= bfd_get_32 (input_bfd
, hit_data
);
1166 tmp
= tmp
& 0xFF000000;
1168 /* Somehow these are both 4 too far, so subtract 8. */
1169 ret_offset
= s
->output_offset
1171 + s
->output_section
->vma
1172 - (input_section
->output_offset
1173 + input_section
->output_section
->vma
1177 tmp
= tmp
| ((ret_offset
>> 2) & 0x00FFFFFF);
1179 bfd_put_32 (output_bfd
, tmp
, hit_data
1180 - input_section
->vma
);
1184 /* Perform a relocation as part of a final link. */
1185 static bfd_reloc_status_type
1186 elf32_arm_final_link_relocate (howto
, input_bfd
, output_bfd
,
1187 input_section
, contents
, offset
, value
,
1188 addend
, info
, sym_sec
, sym_name
, sym_flags
)
1189 reloc_howto_type
*howto
;
1192 asection
*input_section
;
1197 struct bfd_link_info
*info
;
1199 const char *sym_name
;
1200 unsigned char sym_flags
;
1202 unsigned long r_type
= howto
->type
;
1203 bfd_byte
*hit_data
= contents
+ offset
;
1209 return bfd_reloc_ok
;
1212 /* Arm B/BL instruction */
1214 /* check for arm calling thumb function */
1215 if (sym_flags
== STT_ARM_TFUNC
)
1217 elf32_arm_to_thumb_stub (info
, sym_name
, input_bfd
, output_bfd
,
1218 input_section
, hit_data
, sym_sec
, offset
, addend
, value
);
1219 return bfd_reloc_ok
;
1222 value
= value
+ addend
;
1223 value
-= (input_section
->output_section
->vma
1224 + input_section
->output_offset
+ 8);
1226 value
= value
>> howto
->rightshift
;
1229 value
|= (bfd_get_32 (input_bfd
, hit_data
) & 0xff000000);
1230 bfd_put_32 (input_bfd
, value
, hit_data
);
1231 return bfd_reloc_ok
;
1235 if (sym_flags
== STT_ARM_TFUNC
)
1237 bfd_put_32 (input_bfd
, value
, hit_data
);
1238 return bfd_reloc_ok
;
1241 value
-= (input_section
->output_section
->vma
1242 + input_section
->output_offset
);
1245 bfd_put_32 (input_bfd
, value
, hit_data
);
1246 return bfd_reloc_ok
;
1251 if ((long) value
> 0x7f || (long) value
< -0x80)
1252 return bfd_reloc_overflow
;
1254 bfd_put_8 (input_bfd
, value
, hit_data
);
1255 return bfd_reloc_ok
;
1260 if ((long) value
> 0x7fff || (long) value
< -0x8000)
1261 return bfd_reloc_overflow
;
1263 bfd_put_16 (input_bfd
, value
, hit_data
);
1264 return bfd_reloc_ok
;
1267 /* Support ldr and str instruction for the arm */
1268 /* Also thumb b (unconditional branch) */
1271 if ((long) value
> 0x7ff || (long) value
< -0x800)
1272 return bfd_reloc_overflow
;
1274 value
|= (bfd_get_32 (input_bfd
, hit_data
) & 0xfffff000);
1275 bfd_put_32 (input_bfd
, value
, hit_data
);
1276 return bfd_reloc_ok
;
1278 case R_ARM_THM_ABS5
:
1279 /* Support ldr and str instructions for the thumb. */
1282 if ((long) value
> 0x1f || (long) value
< -0x10)
1283 return bfd_reloc_overflow
;
1285 value
|= bfd_get_16 (input_bfd
, hit_data
) & 0xf82f;
1286 bfd_put_16 (input_bfd
, value
, hit_data
);
1287 return bfd_reloc_ok
;
1290 case R_ARM_THM_PC22
:
1291 /* thumb BL (branch long instruction). */
1294 boolean overflow
= false;
1295 bfd_vma insn
= bfd_get_32 (input_bfd
, hit_data
);
1296 bfd_vma src_mask
= 0x007FFFFE;
1297 bfd_signed_vma reloc_signed_max
= (1 << (howto
->bitsize
- 1)) - 1;
1298 bfd_signed_vma reloc_signed_min
= ~reloc_signed_max
;
1300 bfd_signed_vma signed_check
;
1302 bfd_signed_vma signed_add
;
1304 /* If it's not a call to thumb, assume call to arm */
1305 if (sym_flags
!= STT_ARM_TFUNC
)
1307 elf32_thumb_to_arm_stub (info
, sym_name
, input_bfd
, output_bfd
, input_section
,
1308 hit_data
, sym_sec
, offset
, addend
, value
);
1309 return bfd_reloc_ok
;
1312 relocation
= value
+ addend
;
1313 relocation
-= (input_section
->output_section
->vma
+ input_section
->output_offset
);
1314 relocation
-= offset
;
1316 check
= relocation
>> howto
->rightshift
;
1318 /* If this is a signed value, the rightshift just dropped
1319 leading 1 bits (assuming twos complement). */
1320 if ((bfd_signed_vma
) relocation
>= 0)
1321 signed_check
= check
;
1323 signed_check
= (check
| ((bfd_vma
) - 1 & ~((bfd_vma
) - 1 >> howto
->rightshift
)));
1325 /* Get the value from the object file. */
1326 if (bfd_big_endian (input_bfd
))
1327 add
= (((insn
) & 0x07ff0000) >> 4) | (((insn
) & 0x7ff) << 1);
1329 add
= ((((insn
) & 0x7ff) << 12) | (((insn
) & 0x07ff0000) >> 15));
1331 /* Get the value from the object file with an appropriate sign.
1332 The expression involving howto->src_mask isolates the upper
1333 bit of src_mask. If that bit is set in the value we are
1334 adding, it is negative, and we subtract out that number times
1335 two. If src_mask includes the highest possible bit, then we
1336 can not get the upper bit, but that does not matter since
1337 signed_add needs no adjustment to become negative in that case. */
1341 if ((add
& (((~src_mask
) >> 1) & src_mask
)) != 0)
1342 signed_add
-= (((~src_mask
) >> 1) & src_mask
) << 1;
1344 /* Add the value from the object file, shifted so that it is a
1346 /* howto->bitpos == 0 */
1348 signed_check
+= signed_add
;
1349 relocation
+= signed_add
;
1351 /* Assumes two's complement. */
1352 if (signed_check
> reloc_signed_max
1353 || signed_check
< reloc_signed_min
)
1356 /* Put RELOCATION into the correct bits: */
1358 if (bfd_big_endian (input_bfd
))
1359 relocation
= (((relocation
& 0xffe) >> 1) | ((relocation
<< 4) & 0x07ff0000));
1361 relocation
= (((relocation
& 0xffe) << 15) | ((relocation
>> 12) & 0x7ff));
1363 /* Add RELOCATION to the correct bits of X: */
1364 insn
= ((insn
& ~howto
->dst_mask
) | relocation
);
1366 /* Put the relocated value back in the object file: */
1367 bfd_put_32 (input_bfd
, insn
, hit_data
);
1369 return (overflow
? bfd_reloc_overflow
: bfd_reloc_ok
);
1374 return bfd_reloc_notsupported
;
1376 case R_ARM_AMP_VCALL9
:
1377 return bfd_reloc_notsupported
;
1379 case R_ARM_RSBREL32
:
1380 return bfd_reloc_notsupported
;
1382 case R_ARM_THM_RPC22
:
1383 return bfd_reloc_notsupported
;
1386 return bfd_reloc_notsupported
;
1389 return bfd_reloc_notsupported
;
1392 return bfd_reloc_notsupported
;
1395 return bfd_reloc_notsupported
;
1398 return bfd_reloc_notsupported
;
1403 /* Relocate an ARM ELF section. */
1405 elf32_arm_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
1406 contents
, relocs
, local_syms
, local_sections
)
1408 struct bfd_link_info
*info
;
1410 asection
*input_section
;
1412 Elf_Internal_Rela
*relocs
;
1413 Elf_Internal_Sym
*local_syms
;
1414 asection
**local_sections
;
1416 Elf_Internal_Shdr
*symtab_hdr
;
1417 struct elf_link_hash_entry
**sym_hashes
;
1418 Elf_Internal_Rela
*rel
, *relend
;
1421 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
1422 sym_hashes
= elf_sym_hashes (input_bfd
);
1425 relend
= relocs
+ input_section
->reloc_count
;
1426 for (; rel
< relend
; rel
++)
1429 reloc_howto_type
*howto
;
1430 unsigned long r_symndx
;
1431 Elf_Internal_Sym
*sym
;
1433 struct elf_link_hash_entry
*h
;
1435 bfd_reloc_status_type r
;
1437 r_symndx
= ELF32_R_SYM (rel
->r_info
);
1438 r_type
= ELF32_R_TYPE (rel
->r_info
);
1439 howto
= elf32_arm_howto_table
+ r_type
;
1441 if (info
->relocateable
)
1443 /* This is a relocateable link. We don't have to change
1444 anything, unless the reloc is against a section symbol,
1445 in which case we have to adjust according to where the
1446 section symbol winds up in the output section. */
1447 if (r_symndx
< symtab_hdr
->sh_info
)
1449 sym
= local_syms
+ r_symndx
;
1450 if (ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
1452 sec
= local_sections
[r_symndx
];
1453 rel
->r_addend
+= sec
->output_offset
+ sym
->st_value
;
1460 /* This is a final link. */
1464 if (r_symndx
< symtab_hdr
->sh_info
)
1466 sym
= local_syms
+ r_symndx
;
1467 sec
= local_sections
[r_symndx
];
1468 relocation
= (sec
->output_section
->vma
1469 + sec
->output_offset
1474 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
1475 while (h
->root
.type
== bfd_link_hash_indirect
1476 || h
->root
.type
== bfd_link_hash_warning
)
1477 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
1478 if (h
->root
.type
== bfd_link_hash_defined
1479 || h
->root
.type
== bfd_link_hash_defweak
)
1481 sec
= h
->root
.u
.def
.section
;
1482 relocation
= (h
->root
.u
.def
.value
1483 + sec
->output_section
->vma
1484 + sec
->output_offset
);
1486 else if (h
->root
.type
== bfd_link_hash_undefweak
)
1490 if (!((*info
->callbacks
->undefined_symbol
)
1491 (info
, h
->root
.root
.string
, input_bfd
,
1492 input_section
, rel
->r_offset
)))
1499 name
= h
->root
.root
.string
;
1502 name
= (bfd_elf_string_from_elf_section
1503 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
));
1504 if (name
== NULL
|| *name
== '\0')
1505 name
= bfd_section_name (input_bfd
, sec
);
1508 r
= elf32_arm_final_link_relocate (howto
, input_bfd
, output_bfd
,
1510 contents
, rel
->r_offset
,
1511 relocation
, rel
->r_addend
,
1513 (h
? ELF_ST_TYPE (h
->type
) : ELF_ST_TYPE (sym
->st_info
)));
1516 if (r
!= bfd_reloc_ok
)
1518 const char *msg
= (const char *) 0;
1522 case bfd_reloc_overflow
:
1523 if (!((*info
->callbacks
->reloc_overflow
)
1524 (info
, name
, howto
->name
, (bfd_vma
) 0,
1525 input_bfd
, input_section
, rel
->r_offset
)))
1529 case bfd_reloc_undefined
:
1530 if (!((*info
->callbacks
->undefined_symbol
)
1531 (info
, name
, input_bfd
, input_section
,
1536 case bfd_reloc_outofrange
:
1537 msg
= _ ("internal error: out of range error");
1540 case bfd_reloc_notsupported
:
1541 msg
= _ ("internal error: unsupported relocation error");
1544 case bfd_reloc_dangerous
:
1545 msg
= _ ("internal error: dangerous error");
1549 msg
= _ ("internal error: unknown error");
1553 if (!((*info
->callbacks
->warning
)
1554 (info
, msg
, name
, input_bfd
, input_section
,
1565 /* Function to keep ARM specific flags in the ELF header. */
1567 elf32_arm_set_private_flags (abfd
, flags
)
1571 if (elf_flags_init (abfd
)
1572 && elf_elfheader (abfd
)->e_flags
!= flags
)
1574 if (flags
& EF_INTERWORK
)
1575 _bfd_error_handler (_ ("\
1576 Warning: Not setting interwork flag of %s since it has already been specified as non-interworking"),
1577 bfd_get_filename (abfd
));
1579 _bfd_error_handler (_ ("\
1580 Warning: Clearing the interwork flag of %s due to outside request"),
1581 bfd_get_filename (abfd
));
1585 elf_elfheader (abfd
)->e_flags
= flags
;
1586 elf_flags_init (abfd
) = true;
1592 /* Copy backend specific data from one object module to another */
1594 elf32_arm_copy_private_bfd_data (ibfd
, obfd
)
1601 if (bfd_get_flavour (ibfd
) != bfd_target_elf_flavour
1602 || bfd_get_flavour (obfd
) != bfd_target_elf_flavour
)
1605 in_flags
= elf_elfheader (ibfd
)->e_flags
;
1606 out_flags
= elf_elfheader (obfd
)->e_flags
;
1608 if (elf_flags_init (obfd
) && in_flags
!= out_flags
)
1610 /* Cannot mix PIC and non-PIC code. */
1611 if ((in_flags
& EF_PIC
) != (out_flags
& EF_PIC
))
1614 /* Cannot mix APCS26 and APCS32 code. */
1615 if ((in_flags
& EF_APCS_26
) != (out_flags
& EF_APCS_26
))
1618 /* Cannot mix float APCS and non-float APCS code. */
1619 if ((in_flags
& EF_APCS_FLOAT
) != (out_flags
& EF_APCS_FLOAT
))
1622 /* If the src and dest have different interworking flags
1623 then turn off the interworking bit. */
1624 if ((in_flags
& EF_INTERWORK
) != (out_flags
& EF_INTERWORK
))
1626 if (out_flags
& EF_INTERWORK
)
1627 _bfd_error_handler (_ ("\
1628 Warning: Clearing the interwork flag in %s because non-interworking code in %s has been linked with it"),
1629 bfd_get_filename (obfd
), bfd_get_filename (ibfd
));
1631 in_flags
&= ~EF_INTERWORK
;
1635 elf_elfheader (obfd
)->e_flags
= in_flags
;
1636 elf_flags_init (obfd
) = true;
1641 /* Merge backend specific data from an object file to the output
1642 object file when linking. */
1644 elf32_arm_merge_private_bfd_data (ibfd
, obfd
)
1651 if (bfd_get_flavour (ibfd
) != bfd_target_elf_flavour
1652 || bfd_get_flavour (obfd
) != bfd_target_elf_flavour
)
1655 /* The input BFD must have had its flags initialised. */
1656 /* The following seems bogus to me -- The flags are initialized in
1657 the assembler but I don't think an elf_flags_init field is
1658 written into the object */
1659 /* BFD_ASSERT (elf_flags_init (ibfd)); */
1661 in_flags
= elf_elfheader (ibfd
)->e_flags
;
1662 out_flags
= elf_elfheader (obfd
)->e_flags
;
1664 if (!elf_flags_init (obfd
))
1666 /* If the input is the default architecture then do not
1667 bother setting the flags for the output architecture,
1668 instead allow future merges to do this. If no future
1669 merges ever set these flags then they will retain their
1670 unitialised values, which surprise surprise, correspond
1671 to the default values. */
1672 if (bfd_get_arch_info (ibfd
)->the_default
)
1675 elf_flags_init (obfd
) = true;
1676 elf_elfheader (obfd
)->e_flags
= in_flags
;
1678 if (bfd_get_arch (obfd
) == bfd_get_arch (ibfd
)
1679 && bfd_get_arch_info (obfd
)->the_default
)
1680 return bfd_set_arch_mach (obfd
, bfd_get_arch (ibfd
), bfd_get_mach (ibfd
));
1685 /* Check flag compatibility. */
1686 if (in_flags
== out_flags
)
1689 /* Complain about various flag mismatches. */
1691 if ((in_flags
& EF_APCS_26
) != (out_flags
& EF_APCS_26
))
1692 _bfd_error_handler (_ ("\
1693 Error: %s compiled for APCS-%d, whereas %s is compiled for APCS-%d"),
1694 bfd_get_filename (ibfd
),
1695 in_flags
& EF_APCS_26
? 26 : 32,
1696 bfd_get_filename (obfd
),
1697 out_flags
& EF_APCS_26
? 26 : 32);
1699 if ((in_flags
& EF_APCS_FLOAT
) != (out_flags
& EF_APCS_FLOAT
))
1700 _bfd_error_handler (_ ("\
1701 Error: %s passes floats in %s registers, whereas %s passes them in %s registers"),
1702 bfd_get_filename (ibfd
),
1703 in_flags
& EF_APCS_FLOAT
? _ ("float") : _ ("integer"),
1704 bfd_get_filename (obfd
),
1705 out_flags
& EF_APCS_26
? _ ("float") : _ ("integer"));
1707 if ((in_flags
& EF_PIC
) != (out_flags
& EF_PIC
))
1708 _bfd_error_handler (_ ("\
1709 Error: %s is compiled as position %s code, whereas %s is not"),
1710 bfd_get_filename (ibfd
),
1711 in_flags
& EF_PIC
? _ ("independent") : _ ("dependent"),
1712 bfd_get_filename (obfd
));
1714 /* Interworking mismatch is only a warning. */
1715 if ((in_flags
& EF_INTERWORK
) != (out_flags
& EF_INTERWORK
))
1717 _bfd_error_handler (_ ("\
1718 Warning: %s %s interworking, whereas %s %s"),
1719 bfd_get_filename (ibfd
),
1720 in_flags
& EF_INTERWORK
? _ ("supports") : _ ("does not support"),
1721 bfd_get_filename (obfd
),
1722 out_flags
& EF_INTERWORK
? _ ("does not") : _ ("does"));
1729 /* Display the flags field */
1731 elf32_arm_print_private_bfd_data (abfd
, ptr
)
1735 FILE *file
= (FILE *) ptr
;
1737 BFD_ASSERT (abfd
!= NULL
&& ptr
!= NULL
);
1739 /* Print normal ELF private data. */
1740 _bfd_elf_print_private_bfd_data (abfd
, ptr
);
1742 /* Ignore init flag - it may not be set, despite the flags field containing valid data. */
1744 /* xgettext:c-format */
1745 fprintf (file
, _ ("private flags = %lx:"), elf_elfheader (abfd
)->e_flags
);
1747 if (elf_elfheader (abfd
)->e_flags
& EF_INTERWORK
)
1748 fprintf (file
, _ (" [interworking enabled]"));
1750 fprintf (file
, _ (" [interworking not enabled]"));
1752 if (elf_elfheader (abfd
)->e_flags
& EF_APCS_26
)
1753 fprintf (file
, _ (" [APCS-26]"));
1755 fprintf (file
, _ (" [APCS-32]"));
1757 if (elf_elfheader (abfd
)->e_flags
& EF_APCS_FLOAT
)
1758 fprintf (file
, _ (" [floats passed in float registers]"));
1760 fprintf (file
, _ (" [floats passed in integer registers]"));
1762 if (elf_elfheader (abfd
)->e_flags
& EF_PIC
)
1763 fprintf (file
, _ (" [position independent]"));
1765 fprintf (file
, _ (" [absolute position]"));
1773 elf32_arm_get_symbol_type (elf_sym
)
1774 Elf_Internal_Sym
*elf_sym
;
1776 return ELF_ST_TYPE(elf_sym
->st_info
);
1780 #define TARGET_LITTLE_SYM bfd_elf32_littlearm_vec
1781 #define TARGET_LITTLE_NAME "elf32-littlearm"
1782 #define TARGET_BIG_SYM bfd_elf32_bigarm_vec
1783 #define TARGET_BIG_NAME "elf32-bigarm"
1784 #define ELF_ARCH bfd_arch_arm
1785 #define ELF_MACHINE_CODE EM_ARM
1787 #define bfd_elf32_bfd_reloc_type_lookup elf32_arm_reloc_type_lookup
1788 #define elf_info_to_howto elf32_arm_info_to_howto
1789 #define elf_info_to_howto_rel 0
1790 #define elf_backend_relocate_section elf32_arm_relocate_section
1791 #define bfd_elf32_bfd_copy_private_bfd_data elf32_arm_copy_private_bfd_data
1792 #define bfd_elf32_bfd_merge_private_bfd_data elf32_arm_merge_private_bfd_data
1793 #define bfd_elf32_bfd_set_private_flags elf32_arm_set_private_flags
1794 #define bfd_elf32_bfd_print_private_bfd_data elf32_arm_print_private_bfd_data
1795 #define bfd_elf32_bfd_link_hash_table_create elf32_arm_link_hash_table_create
1796 #define elf_backend_get_symbol_type elf32_arm_get_symbol_type
1797 #define elf_symbol_leading_char '_'
1799 #include "elf32-target.h"