1 /* start-sanitize-armelf */
2 /* 32-bit ELF support for ARM
3 Copyright 1993, 1995, 1998 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
28 typedef unsigned long int insn32
;
29 typedef unsigned short int insn16
;
31 static reloc_howto_type
*elf32_arm_reloc_type_lookup
32 PARAMS ((bfd
* abfd
, bfd_reloc_code_real_type code
));
33 static void elf32_arm_info_to_howto
34 PARAMS ((bfd
*, arelent
*, Elf32_Internal_Rela
*));
35 static boolean elf32_arm_set_private_flags
36 PARAMS ((bfd
*, flagword
));
37 static boolean elf32_arm_copy_private_bfd_data
38 PARAMS ((bfd
*, bfd
*));
39 static boolean elf32_arm_merge_private_bfd_data
40 PARAMS ((bfd
*, bfd
*));
41 static boolean elf32_arm_print_private_bfd_data
42 PARAMS ((bfd
*, PTR
));
43 static struct bfd_link_hash_table
*elf32_arm_link_hash_table_create
47 static insn32 insert_thumb_branch
48 PARAMS ((insn32
, int));
49 static struct elf_link_hash_entry
*find_thumb_glue
50 PARAMS ((struct bfd_link_info
*, CONST
char *, bfd
*));
51 static struct elf_link_hash_entry
*find_arm_glue
52 PARAMS ((struct bfd_link_info
*, CONST
char *, bfd
*));
53 static void record_arm_to_thumb_glue
54 PARAMS ((struct bfd_link_info
*, struct elf_link_hash_entry
*));
55 static void record_thumb_to_arm_glue
56 PARAMS ((struct bfd_link_info
*, struct elf_link_hash_entry
*));
58 /* The linker script knows the section names for placement.
59 The entry_names are used to do simple name mangling on the stubs.
60 Given a function name, and its type, the stub can be found. The
61 name can be changed. The only requirement is the %s be present.
64 #define INTERWORK_FLAG( abfd ) (elf_elfheader (abfd)->e_flags & EF_INTERWORK)
66 #define THUMB2ARM_GLUE_SECTION_NAME ".glue_7t"
67 #define THUMB2ARM_GLUE_ENTRY_NAME "__%s_from_thumb"
69 #define ARM2THUMB_GLUE_SECTION_NAME ".glue_7"
70 #define ARM2THUMB_GLUE_ENTRY_NAME "__%s_from_arm"
72 /* Get the ARM elf linker hash table from a link_info structure. */
73 #define elf32_arm_hash_table(info) \
74 ((struct elf32_arm_link_hash_table *) ((info)->hash))
76 /* ARM ELF linker hash table */
77 struct elf32_arm_link_hash_table
79 /* The main hash table. */
80 struct elf_link_hash_table root
;
82 /* The size in bytes of the section containg the Thumb-to-ARM glue. */
83 long int thumb_glue_size
;
85 /* The size in bytes of the section containg the ARM-to-Thumb glue. */
86 long int arm_glue_size
;
88 /* An arbitary input BFD chosen to hold the glue sections. */
89 bfd
*bfd_of_glue_owner
;
95 /* Create an ARM elf linker hash table */
97 static struct bfd_link_hash_table
*
98 elf32_arm_link_hash_table_create (abfd
)
101 struct elf32_arm_link_hash_table
*ret
;
103 ret
= ((struct elf32_arm_link_hash_table
*)
104 bfd_alloc (abfd
, sizeof (struct elf32_arm_link_hash_table
)));
105 if (ret
== (struct elf32_arm_link_hash_table
*) NULL
)
108 if (!_bfd_elf_link_hash_table_init (&ret
->root
, abfd
,
109 _bfd_elf_link_hash_newfunc
))
111 bfd_release (abfd
, ret
);
115 ret
->thumb_glue_size
= 0;
116 ret
->arm_glue_size
= 0;
117 ret
->bfd_of_glue_owner
= NULL
;
119 return &ret
->root
.root
;
122 static struct elf_link_hash_entry
*
123 find_thumb_glue (link_info
, name
, input_bfd
)
124 struct bfd_link_info
*link_info
;
129 struct elf_link_hash_entry
*hash
;
130 struct elf32_arm_link_hash_table
*hash_table
;
132 /* We need a pointer to the armelf specific hash table. */
133 hash_table
= elf32_arm_hash_table (link_info
);
137 bfd_malloc (strlen (name
) + strlen (THUMB2ARM_GLUE_ENTRY_NAME
) + 1));
139 BFD_ASSERT (tmp_name
);
141 sprintf (tmp_name
, THUMB2ARM_GLUE_ENTRY_NAME
, name
);
143 hash
= elf_link_hash_lookup
144 (&(hash_table
)->root
, tmp_name
, false, false, true);
147 /* xgettext:c-format */
148 _bfd_error_handler (_ ("%s: unable to find THUMB glue '%s' for `%s'"),
149 bfd_get_filename (input_bfd
), tmp_name
, name
);
156 static struct elf_link_hash_entry
*
157 find_arm_glue (link_info
, name
, input_bfd
)
158 struct bfd_link_info
*link_info
;
163 struct elf_link_hash_entry
*myh
;
164 struct elf32_arm_link_hash_table
*hash_table
;
166 /* We need a pointer to the elfarm specific hash table. */
167 hash_table
= elf32_arm_hash_table (link_info
);
170 bfd_malloc (strlen (name
) + strlen (ARM2THUMB_GLUE_ENTRY_NAME
) + 1));
172 BFD_ASSERT (tmp_name
);
174 sprintf (tmp_name
, ARM2THUMB_GLUE_ENTRY_NAME
, name
);
176 myh
= elf_link_hash_lookup
177 (&(hash_table
)->root
, tmp_name
, false, false, true);
180 /* xgettext:c-format */
181 _bfd_error_handler (_ ("%s: unable to find ARM glue '%s' for `%s'"),
182 bfd_get_filename (input_bfd
), tmp_name
, name
);
197 .word func @ behave as if you saw a ARM_32 reloc
200 #define ARM2THUMB_GLUE_SIZE 12
201 static const insn32 a2t1_ldr_insn
= 0xe59fc000;
202 static const insn32 a2t2_bx_r12_insn
= 0xe12fff1c;
203 static const insn32 a2t3_func_addr_insn
= 0x00000001;
206 Thumb->ARM: Thumb->(non-interworking aware) ARM
210 __func_from_thumb: __func_from_thumb:
212 nop ldr r6, __func_addr
214 __func_change_to_arm: bx r6
216 __func_back_to_thumb:
223 #define THUMB2ARM_GLUE_SIZE 8
224 static const insn16 t2a1_bx_pc_insn
= 0x4778;
225 static const insn16 t2a2_noop_insn
= 0x46c0;
226 static const insn32 t2a3_b_insn
= 0xea000000;
228 static const insn16 t2a1_push_insn
= 0xb540;
229 static const insn16 t2a2_ldr_insn
= 0x4e03;
230 static const insn16 t2a3_mov_insn
= 0x46fe;
231 static const insn16 t2a4_bx_insn
= 0x4730;
232 static const insn32 t2a5_pop_insn
= 0xe8bd4040;
233 static const insn32 t2a6_bx_insn
= 0xe12fff1e;
236 bfd_elf32_arm_allocate_interworking_sections (info
)
237 struct bfd_link_info
*info
;
241 struct elf32_arm_link_hash_table
*globals
;
243 globals
= elf32_arm_hash_table (info
);
245 BFD_ASSERT (globals
!= NULL
);
247 if (globals
->arm_glue_size
!= 0)
249 BFD_ASSERT (globals
->bfd_of_glue_owner
!= NULL
);
251 s
= bfd_get_section_by_name
252 (globals
->bfd_of_glue_owner
, ARM2THUMB_GLUE_SECTION_NAME
);
254 BFD_ASSERT (s
!= NULL
);
256 foo
= (bfd_byte
*) bfd_alloc
257 (globals
->bfd_of_glue_owner
, globals
->arm_glue_size
);
259 s
->_raw_size
= s
->_cooked_size
= globals
->arm_glue_size
;
263 if (globals
->thumb_glue_size
!= 0)
265 BFD_ASSERT (globals
->bfd_of_glue_owner
!= NULL
);
267 s
= bfd_get_section_by_name
268 (globals
->bfd_of_glue_owner
, THUMB2ARM_GLUE_SECTION_NAME
);
270 BFD_ASSERT (s
!= NULL
);
272 foo
= (bfd_byte
*) bfd_alloc
273 (globals
->bfd_of_glue_owner
, globals
->thumb_glue_size
);
275 s
->_raw_size
= s
->_cooked_size
= globals
->thumb_glue_size
;
283 record_arm_to_thumb_glue (link_info
, h
)
284 struct bfd_link_info
*link_info
;
285 struct elf_link_hash_entry
*h
;
287 const char *name
= h
->root
.root
.string
;
288 register asection
*s
;
290 struct elf_link_hash_entry
*myh
;
291 struct elf32_arm_link_hash_table
*globals
;
293 globals
= elf32_arm_hash_table (link_info
);
295 BFD_ASSERT (globals
!= NULL
);
296 BFD_ASSERT (globals
->bfd_of_glue_owner
!= NULL
);
298 s
= bfd_get_section_by_name
299 (globals
->bfd_of_glue_owner
, ARM2THUMB_GLUE_SECTION_NAME
);
302 BFD_ASSERT (s
!= NULL
);
305 bfd_malloc (strlen (name
) + strlen (ARM2THUMB_GLUE_ENTRY_NAME
) + 1));
307 BFD_ASSERT (tmp_name
);
309 sprintf (tmp_name
, ARM2THUMB_GLUE_ENTRY_NAME
, name
);
311 myh
= elf_link_hash_lookup
312 (&(globals
)->root
, tmp_name
, false, false, true);
317 return; /* we've already seen this guy */
320 /* The only trick here is using hash_table->arm_glue_size as the value. Even
321 though the section isn't allocated yet, this is where we will be putting
324 _bfd_generic_link_add_one_symbol (link_info
, globals
->bfd_of_glue_owner
, tmp_name
,
326 s
, globals
->arm_glue_size
+ 1,
328 (struct bfd_link_hash_entry
**) &myh
);
332 globals
->arm_glue_size
+= ARM2THUMB_GLUE_SIZE
;
338 record_thumb_to_arm_glue (link_info
, h
)
339 struct bfd_link_info
*link_info
;
340 struct elf_link_hash_entry
*h
;
342 const char *name
= h
->root
.root
.string
;
343 register asection
*s
;
345 struct elf_link_hash_entry
*myh
;
346 struct elf32_arm_link_hash_table
*hash_table
;
348 hash_table
= elf32_arm_hash_table (link_info
);
350 BFD_ASSERT (hash_table
!= NULL
);
351 BFD_ASSERT (hash_table
->bfd_of_glue_owner
!= NULL
);
353 s
= bfd_get_section_by_name
354 (hash_table
->bfd_of_glue_owner
, THUMB2ARM_GLUE_SECTION_NAME
);
356 BFD_ASSERT (s
!= NULL
);
358 tmp_name
= (char *) bfd_malloc (strlen (name
) + strlen (THUMB2ARM_GLUE_ENTRY_NAME
) + 1);
360 BFD_ASSERT (tmp_name
);
362 sprintf (tmp_name
, THUMB2ARM_GLUE_ENTRY_NAME
, name
);
364 myh
= elf_link_hash_lookup
365 (&(hash_table
)->root
, tmp_name
, false, false, true);
370 return; /* we've already seen this guy */
373 _bfd_generic_link_add_one_symbol (link_info
, hash_table
->bfd_of_glue_owner
, tmp_name
,
374 BSF_GLOBAL
, s
, hash_table
->thumb_glue_size
+ 1,
376 (struct bfd_link_hash_entry
**) &myh
);
378 /* If we mark it 'thumb', the disassembler will do a better job. */
379 myh
->other
= C_THUMBEXTFUNC
;
383 /* Allocate another symbol to mark where we switch to arm mode. */
385 #define CHANGE_TO_ARM "__%s_change_to_arm"
386 #define BACK_FROM_ARM "__%s_back_from_arm"
388 tmp_name
= (char *) bfd_malloc (strlen (name
) + strlen (CHANGE_TO_ARM
) + 1);
390 BFD_ASSERT (tmp_name
);
392 sprintf (tmp_name
, CHANGE_TO_ARM
, name
);
396 _bfd_generic_link_add_one_symbol (link_info
, hash_table
->bfd_of_glue_owner
, tmp_name
,
397 BSF_LOCAL
, s
, hash_table
->thumb_glue_size
+ 4,
399 (struct bfd_link_hash_entry
**) &myh
);
403 hash_table
->thumb_glue_size
+= THUMB2ARM_GLUE_SIZE
;
408 /* Select a BFD to be used to hold the sections used by the glue code.
409 This function is called from the linker scripts in ld/emultempl/
412 bfd_elf32_arm_get_bfd_for_interworking (abfd
, info
)
414 struct bfd_link_info
*info
;
416 struct elf32_arm_link_hash_table
*globals
;
420 /* If we are only performing a partial link do not bother
421 getting a bfd to hold the glue. */
422 if (info
->relocateable
)
425 globals
= elf32_arm_hash_table (info
);
427 BFD_ASSERT (globals
!= NULL
);
429 if (globals
->bfd_of_glue_owner
!= NULL
)
432 sec
= bfd_get_section_by_name (abfd
, ARM2THUMB_GLUE_SECTION_NAME
);
436 flags
= SEC_ALLOC
| SEC_LOAD
| SEC_HAS_CONTENTS
| SEC_IN_MEMORY
;
438 sec
= bfd_make_section (abfd
, ARM2THUMB_GLUE_SECTION_NAME
);
441 || !bfd_set_section_flags (abfd
, sec
, flags
)
442 || !bfd_set_section_alignment (abfd
, sec
, 2))
446 sec
= bfd_get_section_by_name (abfd
, THUMB2ARM_GLUE_SECTION_NAME
);
450 flags
= SEC_ALLOC
| SEC_LOAD
| SEC_HAS_CONTENTS
| SEC_IN_MEMORY
;
452 sec
= bfd_make_section (abfd
, THUMB2ARM_GLUE_SECTION_NAME
);
455 || !bfd_set_section_flags (abfd
, sec
, flags
)
456 || !bfd_set_section_alignment (abfd
, sec
, 2))
460 /* Save the bfd for later use. */
461 globals
->bfd_of_glue_owner
= abfd
;
467 bfd_elf32_arm_process_before_allocation (abfd
, link_info
)
469 struct bfd_link_info
*link_info
;
471 Elf_Internal_Shdr
*symtab_hdr
;
472 Elf_Internal_Rela
*free_relocs
= NULL
;
473 Elf_Internal_Rela
*irel
, *irelend
;
474 bfd_byte
*contents
= NULL
;
475 bfd_byte
*free_contents
= NULL
;
476 Elf32_External_Sym
*extsyms
= NULL
;
477 Elf32_External_Sym
*free_extsyms
= NULL
;
480 struct elf32_arm_link_hash_table
*globals
;
482 /* If we are only performing a partial link do not bother
483 to construct any glue. */
484 if (link_info
->relocateable
)
487 /* Here we have a bfd that is to be included on the link. We have a hook
488 to do reloc rummaging, before section sizes are nailed down. */
490 /* _bfd_coff_get_external_symbols (abfd); */
492 globals
= elf32_arm_hash_table (link_info
);
494 BFD_ASSERT (globals
!= NULL
);
495 BFD_ASSERT (globals
->bfd_of_glue_owner
!= NULL
);
497 /* Rummage around all the relocs and map the glue vectors. */
498 sec
= abfd
->sections
;
503 for (; sec
!= NULL
; sec
= sec
->next
)
505 struct internal_reloc
*i
;
506 struct internal_reloc
*rel
;
508 if (sec
->reloc_count
== 0)
511 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
512 /* Load the relocs. */
514 irel
= (_bfd_elf32_link_read_relocs (abfd
, sec
, (PTR
) NULL
,
515 (Elf_Internal_Rela
*) NULL
, false));
519 irelend
= irel
+ sec
->reloc_count
;
520 for (; irel
< irelend
; irel
++)
523 unsigned long r_index
;
526 struct elf_link_hash_entry
*h
;
528 r_type
= ELF32_R_TYPE (irel
->r_info
);
529 r_index
= ELF32_R_SYM (irel
->r_info
);
531 /* These are the only relocation types we care about */
532 if (r_type
!= R_ARM_PC24
533 && r_type
!= R_ARM_THM_PC22
)
536 /* Get the section contents if we haven't done so already. */
537 if (contents
== NULL
)
539 /* Get cached copy if it exists. */
540 if (elf_section_data (sec
)->this_hdr
.contents
!= NULL
)
541 contents
= elf_section_data (sec
)->this_hdr
.contents
;
544 /* Go get them off disk. */
545 contents
= (bfd_byte
*) bfd_malloc (sec
->_raw_size
);
546 if (contents
== NULL
)
548 free_contents
= contents
;
550 if (!bfd_get_section_contents (abfd
, sec
, contents
,
551 (file_ptr
) 0, sec
->_raw_size
))
556 /* Read this BFD's symbols if we haven't done so already. */
559 /* Get cached copy if it exists. */
560 if (symtab_hdr
->contents
!= NULL
)
561 extsyms
= (Elf32_External_Sym
*) symtab_hdr
->contents
;
564 /* Go get them off disk. */
565 extsyms
= ((Elf32_External_Sym
*)
566 bfd_malloc (symtab_hdr
->sh_size
));
569 free_extsyms
= extsyms
;
570 if (bfd_seek (abfd
, symtab_hdr
->sh_offset
, SEEK_SET
) != 0
571 || (bfd_read (extsyms
, 1, symtab_hdr
->sh_size
, abfd
)
572 != symtab_hdr
->sh_size
))
577 /* If the relocation is not against a symbol it cannot concern us. */
581 /* We don't care about local symbols */
582 if (r_index
< symtab_hdr
->sh_info
)
585 /* This is an external symbol */
586 r_index
-= symtab_hdr
->sh_info
;
587 h
= (struct elf_link_hash_entry
*)
588 elf_sym_hashes (abfd
)[r_index
];
590 /* If the relocation is against a static symbol it must be within
591 the current section and so cannot be a cross ARM/Thumb relocation. */
598 /* This one is a call from arm code. We need to look up
599 the target of the call. If it is a thumb target, we
602 if (h
->other
== C_THUMBEXTFUNC
)
603 record_arm_to_thumb_glue (link_info
, h
);
608 /* This one is a call from thumb code. We used to look
609 for ARM_THUMB9 and ARM_THUMB12 as well. We need to look
610 up the target of the call. If it is an arm target, we
611 insert glue. If the symbol does not exist it will be
612 given a class of C_EXT and so we will generate a stub
613 for it. This is not really a problem, since the link
621 record_thumb_to_arm_glue (link_info
, h
);
636 if (free_relocs
!= NULL
)
638 if (free_contents
!= NULL
)
639 free (free_contents
);
640 if (free_extsyms
!= NULL
)
647 #define TARGET_UNDERSCORE '_'
649 static reloc_howto_type elf32_arm_howto_table
[] =
652 HOWTO (R_ARM_NONE
, /* type */
654 0, /* size (0 = byte, 1 = short, 2 = long) */
656 false, /* pc_relative */
658 complain_overflow_dont
, /* complain_on_overflow */
659 bfd_elf_generic_reloc
, /* special_function */
660 "R_ARM_NONE", /* name */
661 false, /* partial_inplace */
664 false), /* pcrel_offset */
666 HOWTO (R_ARM_PC24
, /* type */
668 2, /* size (0 = byte, 1 = short, 2 = long) */
670 true, /* pc_relative */
672 complain_overflow_signed
, /* complain_on_overflow */
673 bfd_elf_generic_reloc
, /* special_function */
674 "R_ARM_PC24", /* name */
675 false, /* partial_inplace */
676 0x00ffffff, /* src_mask */
677 0x00ffffff, /* dst_mask */
678 true), /* pcrel_offset */
680 /* 32 bit absolute */
681 HOWTO (R_ARM_ABS32
, /* type */
683 2, /* size (0 = byte, 1 = short, 2 = long) */
685 false, /* pc_relative */
687 complain_overflow_bitfield
, /* complain_on_overflow */
688 bfd_elf_generic_reloc
, /* special_function */
689 "R_ARM_ABS32", /* name */
690 false, /* partial_inplace */
691 0xffffffff, /* src_mask */
692 0xffffffff, /* dst_mask */
693 false), /* pcrel_offset */
695 /* standard 32bit pc-relative reloc */
696 HOWTO (R_ARM_REL32
, /* type */
698 2, /* size (0 = byte, 1 = short, 2 = long) */
700 true, /* pc_relative */
702 complain_overflow_bitfield
, /* complain_on_overflow */
703 bfd_elf_generic_reloc
, /* special_function */
704 "R_ARM_REL32", /* name */
705 false, /* partial_inplace */
706 0xffffffff, /* src_mask */
707 0xffffffff, /* dst_mask */
708 true), /* pcrel_offset */
711 HOWTO (R_ARM_ABS8
, /* type */
713 0, /* size (0 = byte, 1 = short, 2 = long) */
715 false, /* pc_relative */
717 complain_overflow_bitfield
, /* complain_on_overflow */
718 bfd_elf_generic_reloc
, /* special_function */
719 "R_ARM_ABS8", /* name */
720 false, /* partial_inplace */
721 0x000000ff, /* src_mask */
722 0x000000ff, /* dst_mask */
723 false), /* pcrel_offset */
725 /* 16 bit absolute */
726 HOWTO (R_ARM_ABS16
, /* type */
728 1, /* size (0 = byte, 1 = short, 2 = long) */
730 false, /* pc_relative */
732 complain_overflow_bitfield
, /* complain_on_overflow */
733 bfd_elf_generic_reloc
, /* special_function */
734 "R_ARM_ABS16", /* name */
735 false, /* partial_inplace */
738 false), /* pcrel_offset */
740 /* 12 bit absolute */
741 HOWTO (R_ARM_ABS12
, /* type */
743 2, /* size (0 = byte, 1 = short, 2 = long) */
745 false, /* pc_relative */
747 complain_overflow_bitfield
, /* complain_on_overflow */
748 bfd_elf_generic_reloc
, /* special_function */
749 "R_ARM_ABS12", /* name */
750 false, /* partial_inplace */
751 0x000008ff, /* src_mask */
752 0x000008ff, /* dst_mask */
753 false), /* pcrel_offset */
755 HOWTO (R_ARM_THM_ABS5
, /* type */
757 2, /* size (0 = byte, 1 = short, 2 = long) */
759 false, /* pc_relative */
761 complain_overflow_bitfield
, /* complain_on_overflow */
762 bfd_elf_generic_reloc
, /* special_function */
763 "R_ARM_THM_ABS5", /* name */
764 false, /* partial_inplace */
765 0x000007e0, /* src_mask */
766 0x000007e0, /* dst_mask */
767 false), /* pcrel_offset */
769 HOWTO (R_ARM_THM_PC22
, /* type */
771 2, /* size (0 = byte, 1 = short, 2 = long) */
773 true, /* pc_relative */
775 complain_overflow_signed
, /* complain_on_overflow */
776 bfd_elf_generic_reloc
, /* special_function */
777 "R_ARM_THM_PC22", /* name */
778 false, /* partial_inplace */
779 0x07ff07ff, /* src_mask */
780 0x07ff07ff, /* dst_mask */
781 true), /* pcrel_offset */
783 HOWTO (R_ARM_SBREL32
, /* type */
785 0, /* size (0 = byte, 1 = short, 2 = long) */
787 false, /* pc_relative */
789 complain_overflow_dont
, /* complain_on_overflow */
790 bfd_elf_generic_reloc
, /* special_function */
791 "R_ARM_SBREL32", /* name */
792 false, /* partial_inplace */
795 false), /* pcrel_offset */
797 HOWTO (R_ARM_AMP_VCALL9
, /* type */
799 1, /* size (0 = byte, 1 = short, 2 = long) */
801 true, /* pc_relative */
803 complain_overflow_signed
, /* complain_on_overflow */
804 bfd_elf_generic_reloc
, /* special_function */
805 "R_ARM_AMP_VCALL9", /* name */
806 false, /* partial_inplace */
807 0x000000ff, /* src_mask */
808 0x000000ff, /* dst_mask */
809 true), /* pcrel_offset */
811 /* 12 bit pc relative */
812 HOWTO (R_ARM_THM_PC11
, /* type */
814 1, /* size (0 = byte, 1 = short, 2 = long) */
816 true, /* pc_relative */
818 complain_overflow_signed
, /* complain_on_overflow */
819 bfd_elf_generic_reloc
, /* special_function */
820 "R_ARM_THM_PC11", /* name */
821 false, /* partial_inplace */
822 0x000007ff, /* src_mask */
823 0x000007ff, /* dst_mask */
824 true), /* pcrel_offset */
826 /* 12 bit pc relative */
827 HOWTO (R_ARM_THM_PC9
, /* type */
829 1, /* size (0 = byte, 1 = short, 2 = long) */
831 true, /* pc_relative */
833 complain_overflow_signed
, /* complain_on_overflow */
834 bfd_elf_generic_reloc
, /* special_function */
835 "R_ARM_THM_PC9", /* name */
836 false, /* partial_inplace */
837 0x000000ff, /* src_mask */
838 0x000000ff, /* dst_mask */
839 true), /* pcrel_offset */
841 /* FILL ME IN (#13-249) */
844 HOWTO (R_ARM_RREL32
, /* type */
846 0, /* size (0 = byte, 1 = short, 2 = long) */
848 false, /* pc_relative */
850 complain_overflow_dont
, /* complain_on_overflow */
851 bfd_elf_generic_reloc
, /* special_function */
852 "R_ARM_RREL32", /* name */
853 false, /* partial_inplace */
856 false), /* pcrel_offset */
858 HOWTO (R_ARM_RABS32
, /* type */
860 0, /* size (0 = byte, 1 = short, 2 = long) */
862 false, /* pc_relative */
864 complain_overflow_dont
, /* complain_on_overflow */
865 bfd_elf_generic_reloc
, /* special_function */
866 "R_ARM_RABS32", /* name */
867 false, /* partial_inplace */
870 false), /* pcrel_offset */
872 HOWTO (R_ARM_RPC24
, /* type */
874 0, /* size (0 = byte, 1 = short, 2 = long) */
876 false, /* pc_relative */
878 complain_overflow_dont
, /* complain_on_overflow */
879 bfd_elf_generic_reloc
, /* special_function */
880 "R_ARM_RPC24", /* name */
881 false, /* partial_inplace */
884 false), /* pcrel_offset */
886 HOWTO (R_ARM_RBASE
, /* type */
888 0, /* size (0 = byte, 1 = short, 2 = long) */
890 false, /* pc_relative */
892 complain_overflow_dont
, /* complain_on_overflow */
893 bfd_elf_generic_reloc
, /* special_function */
894 "R_ARM_RBASE", /* name */
895 false, /* partial_inplace */
898 false), /* pcrel_offset */
901 struct elf32_arm_reloc_map
903 unsigned char bfd_reloc_val
;
904 unsigned char elf_reloc_val
;
907 static const struct elf32_arm_reloc_map elf32_arm_reloc_map
[] =
909 {BFD_RELOC_NONE
, R_ARM_NONE
,},
910 {BFD_RELOC_ARM_PCREL_BRANCH
, R_ARM_PC24
,},
911 {BFD_RELOC_32
, R_ARM_ABS32
,},
912 {BFD_RELOC_32_PCREL
, R_ARM_REL32
,},
913 {BFD_RELOC_8
, R_ARM_ABS8
,},
914 {BFD_RELOC_16
, R_ARM_ABS16
,},
915 {BFD_RELOC_ARM_OFFSET_IMM
, R_ARM_ABS12
,},
916 {BFD_RELOC_ARM_THUMB_OFFSET
, R_ARM_THM_ABS5
,},
917 {BFD_RELOC_THUMB_PCREL_BRANCH23
, R_ARM_THM_PC22
,},
918 {BFD_RELOC_NONE
, R_ARM_SBREL32
,},
919 {BFD_RELOC_NONE
, R_ARM_AMP_VCALL9
,},
920 {BFD_RELOC_THUMB_PCREL_BRANCH12
, R_ARM_THM_PC11
,},
921 {BFD_RELOC_THUMB_PCREL_BRANCH9
, R_ARM_THM_PC9
,}
924 static reloc_howto_type
*
925 elf32_arm_reloc_type_lookup (abfd
, code
)
927 bfd_reloc_code_real_type code
;
932 i
< sizeof (elf32_arm_reloc_map
) / sizeof (struct elf32_arm_reloc_map
);
935 if (elf32_arm_reloc_map
[i
].bfd_reloc_val
== code
)
936 return &elf32_arm_howto_table
[elf32_arm_reloc_map
[i
].elf_reloc_val
];
943 elf32_arm_info_to_howto (abfd
, bfd_reloc
, elf_reloc
)
946 Elf32_Internal_Rela
*elf_reloc
;
950 r_type
= ELF32_R_TYPE (elf_reloc
->r_info
);
951 /* fixme: need range test */
952 /* BFD_ASSERT (r_type < (unsigned int) R_ELF32_ARM_MAX); */
953 bfd_reloc
->howto
= &elf32_arm_howto_table
[r_type
];
956 /* The thumb form of a long branch is a bit finicky, because the offset
957 encoding is split over two fields, each in it's own instruction. They
958 can occur in any order. So given a thumb form of long branch, and an
959 offset, insert the offset into the thumb branch and return finished
962 It takes two thumb instructions to encode the target address. Each has
963 11 bits to invest. The upper 11 bits are stored in one (identifed by
964 H-0.. see below), the lower 11 bits are stored in the other (identified
967 Combine together and shifted left by 1 (it's a half word address) and
971 H-0, upper address-0 = 000
973 H-1, lower address-0 = 800
975 They can be ordered either way, but the arm tools I've seen always put
976 the lower one first. It probably doesn't matter. krk@cygnus.com
978 XXX: Actually the order does matter. The second instruction (H-1)
979 moves the computed address into the PC, so it must be the second one
980 in the sequence. The problem, however is that whilst little endian code
981 stores the instructions in HI then LOW order, big endian code does the
982 reverse. nickc@cygnus.com */
984 #define LOW_HI_ORDER 0xF800F000
985 #define HI_LOW_ORDER 0xF000F800
988 insert_thumb_branch (br_insn
, rel_off
)
992 unsigned int low_bits
;
993 unsigned int high_bits
;
996 BFD_ASSERT ((rel_off
& 1) != 1);
998 rel_off
>>= 1; /* half word aligned address */
999 low_bits
= rel_off
& 0x000007FF; /* the bottom 11 bits */
1000 high_bits
= (rel_off
>> 11) & 0x000007FF; /* the top 11 bits */
1002 if ((br_insn
& LOW_HI_ORDER
) == LOW_HI_ORDER
)
1003 br_insn
= LOW_HI_ORDER
| (low_bits
<< 16) | high_bits
;
1004 else if ((br_insn
& HI_LOW_ORDER
) == HI_LOW_ORDER
)
1005 br_insn
= HI_LOW_ORDER
| (high_bits
<< 16) | low_bits
;
1007 abort (); /* error - not a valid branch instruction form */
1009 /* FIXME: abort is probably not the right call. krk@cygnus.com */
1013 elf32_thumb_to_arm_stub (info
, name
, input_bfd
, output_bfd
, input_section
,
1014 hit_data
, sym_sec
, offset
, addend
, val
)
1015 struct bfd_link_info
*info
;
1019 asection
*input_section
;
1027 /* Thumb code calling an ARM function */
1030 unsigned long int tmp
;
1031 long int ret_offset
;
1032 struct elf_link_hash_entry
*myh
;
1033 struct elf32_arm_link_hash_table
*globals
;
1035 myh
= find_thumb_glue (info
, name
, input_bfd
);
1039 globals
= elf32_arm_hash_table (info
);
1041 BFD_ASSERT (globals
!= NULL
);
1042 BFD_ASSERT (globals
->bfd_of_glue_owner
!= NULL
);
1044 my_offset
= myh
->root
.u
.def
.value
;
1046 s
= bfd_get_section_by_name (globals
->bfd_of_glue_owner
,
1047 THUMB2ARM_GLUE_SECTION_NAME
);
1049 BFD_ASSERT (s
!= NULL
);
1050 BFD_ASSERT (s
->contents
!= NULL
);
1051 BFD_ASSERT (s
->output_section
!= NULL
);
1053 if ((my_offset
& 0x01) == 0x01)
1056 if (sym_sec
->owner
!= NULL
1057 && !INTERWORK_FLAG (sym_sec
->owner
))
1060 (_ ("%s(%s): warning: interworking not enabled."),
1061 bfd_get_filename (sym_sec
->owner
), name
);
1063 (_ (" first occurrence: %s: thumb call to arm"),
1064 bfd_get_filename (input_bfd
));
1068 myh
->root
.u
.def
.value
= my_offset
;
1070 bfd_put_16 (output_bfd
, t2a1_bx_pc_insn
,
1071 s
->contents
+ my_offset
);
1073 bfd_put_16 (output_bfd
, t2a2_noop_insn
,
1074 s
->contents
+ my_offset
+ 2);
1077 ((bfd_signed_vma
) val
) /* Address of destination of the stub */
1079 (s
->output_offset
/* Offset from the start of the current section to the start of the stubs. */
1080 + my_offset
/* Offset of the start of this stub from the start of the stubs. */
1081 + s
->output_section
->vma
) /* Address of the start of the current section. */
1082 + 4 /* The branch instruction is 4 bytes into the stub. */
1083 + 8); /* ARM branches work from the pc of the instruction + 8. */
1085 bfd_put_32 (output_bfd
,
1086 t2a3_b_insn
| ((ret_offset
>> 2) & 0x00FFFFFF),
1087 s
->contents
+ my_offset
+ 4);
1090 BFD_ASSERT (my_offset
<= globals
->thumb_glue_size
);
1092 /* Now go back and fix up the original BL insn to point
1097 - (input_section
->output_offset
1101 tmp
= bfd_get_32 (input_bfd
, hit_data
1102 - input_section
->vma
);
1104 bfd_put_32 (output_bfd
,
1105 insert_thumb_branch (tmp
, ret_offset
),
1106 hit_data
- input_section
->vma
);
1108 elf32_arm_to_thumb_stub (info
, name
, input_bfd
, output_bfd
, input_section
,
1109 hit_data
, sym_sec
, offset
, addend
, val
)
1111 struct bfd_link_info
*info
;
1115 asection
*input_section
;
1122 /* Arm code calling a Thumb function */
1123 unsigned long int tmp
;
1126 long int ret_offset
;
1127 struct elf_link_hash_entry
*myh
;
1128 struct elf32_arm_link_hash_table
*globals
;
1130 myh
= find_arm_glue (info
, name
, input_bfd
);
1134 globals
= elf32_arm_hash_table (info
);
1136 BFD_ASSERT (globals
!= NULL
);
1137 BFD_ASSERT (globals
->bfd_of_glue_owner
!= NULL
);
1139 my_offset
= myh
->root
.u
.def
.value
;
1140 s
= bfd_get_section_by_name (globals
->bfd_of_glue_owner
,
1141 ARM2THUMB_GLUE_SECTION_NAME
);
1142 BFD_ASSERT (s
!= NULL
);
1143 BFD_ASSERT (s
->contents
!= NULL
);
1144 BFD_ASSERT (s
->output_section
!= NULL
);
1146 if ((my_offset
& 0x01) == 0x01)
1149 if (sym_sec
->owner
!= NULL
1150 && !INTERWORK_FLAG (sym_sec
->owner
))
1153 (_ ("%s(%s): warning: interworking not enabled."),
1154 bfd_get_filename (sym_sec
->owner
), name
);
1156 (_ (" first occurrence: %s: arm call to thumb"),
1157 bfd_get_filename (input_bfd
));
1160 myh
->root
.u
.def
.value
= my_offset
;
1162 bfd_put_32 (output_bfd
, a2t1_ldr_insn
,
1163 s
->contents
+ my_offset
);
1165 bfd_put_32 (output_bfd
, a2t2_bx_r12_insn
,
1166 s
->contents
+ my_offset
+ 4);
1168 /* It's a thumb address. Add the low order bit. */
1169 bfd_put_32 (output_bfd
, val
| a2t3_func_addr_insn
,
1170 s
->contents
+ my_offset
+ 8);
1173 BFD_ASSERT (my_offset
<= globals
->arm_glue_size
);
1175 tmp
= bfd_get_32 (input_bfd
, hit_data
);
1176 tmp
= tmp
& 0xFF000000;
1178 /* Somehow these are both 4 too far, so subtract 8. */
1179 ret_offset
= s
->output_offset
1181 + s
->output_section
->vma
1182 - (input_section
->output_offset
1183 + input_section
->output_section
->vma
1187 tmp
= tmp
| ((ret_offset
>> 2) & 0x00FFFFFF);
1189 bfd_put_32 (output_bfd
, tmp
, hit_data
1190 - input_section
->vma
);
1193 /* Perform a relocation as part of a final link. */
1194 static bfd_reloc_status_type
1195 elf32_arm_final_link_relocate (howto
, input_bfd
, output_bfd
,
1196 input_section
, contents
, offset
, value
,
1197 addend
, info
, sym_sec
, sym_name
, sym_flags
)
1198 reloc_howto_type
*howto
;
1201 asection
*input_section
;
1206 struct bfd_link_info
*info
;
1209 unsigned char sym_flags
;
1211 unsigned long r_type
= howto
->type
;
1212 bfd_byte
*hit_data
= contents
+ offset
;
1218 return bfd_reloc_ok
;
1221 /* Arm B/BL instruction */
1223 /* check for arm calling thumb function */
1224 if (sym_flags
== C_THUMBSTATFUNC
1225 || sym_flags
== C_THUMBEXTFUNC
)
1227 elf32_arm_to_thumb_stub (info
, sym_name
, input_bfd
, output_bfd
,
1228 input_section
, hit_data
, sym_sec
, offset
, addend
, value
);
1229 return bfd_reloc_ok
;
1232 value
= value
+ addend
;
1233 value
-= (input_section
->output_section
->vma
1234 + input_section
->output_offset
+ 8);
1236 value
= value
>> howto
->rightshift
;
1239 value
|= (bfd_get_32 (input_bfd
, hit_data
) & 0xff000000);
1240 bfd_put_32 (input_bfd
, value
, hit_data
);
1241 return bfd_reloc_ok
;
1245 if (sym_flags
== C_THUMBSTATFUNC
1246 || sym_flags
== C_THUMBEXTFUNC
)
1248 bfd_put_32 (input_bfd
, value
, hit_data
);
1249 return bfd_reloc_ok
;
1252 value
-= (input_section
->output_section
->vma
1253 + input_section
->output_offset
);
1256 bfd_put_32 (input_bfd
, value
, hit_data
);
1257 return bfd_reloc_ok
;
1262 if ((long) value
> 0x7f || (long) value
< -0x80)
1263 return bfd_reloc_overflow
;
1265 bfd_put_8 (input_bfd
, value
, hit_data
);
1266 return bfd_reloc_ok
;
1271 if ((long) value
> 0x7fff || (long) value
< -0x8000)
1272 return bfd_reloc_overflow
;
1274 bfd_put_16 (input_bfd
, value
, hit_data
);
1275 return bfd_reloc_ok
;
1278 /* Support ldr and str instruction for the arm */
1279 /* Also thumb b (unconditional branch) */
1282 if ((long) value
> 0x7ff || (long) value
< -0x800)
1283 return bfd_reloc_overflow
;
1285 value
|= (bfd_get_32 (input_bfd
, hit_data
) & 0xfffff000);
1286 bfd_put_32 (input_bfd
, value
, hit_data
);
1287 return bfd_reloc_ok
;
1289 case R_ARM_THM_ABS5
:
1290 /* Support ldr and str instructions for the thumb. */
1293 if ((long) value
> 0x1f || (long) value
< -0x10)
1294 return bfd_reloc_overflow
;
1296 value
|= bfd_get_16 (input_bfd
, hit_data
) & 0xf82f;
1297 bfd_put_16 (input_bfd
, value
, hit_data
);
1298 return bfd_reloc_ok
;
1301 case R_ARM_THM_PC22
:
1302 /* thumb BL (branch long instruction). */
1305 boolean overflow
= false;
1306 bfd_vma insn
= bfd_get_32 (input_bfd
, hit_data
);
1307 bfd_vma src_mask
= 0x007FFFFE;
1308 bfd_signed_vma reloc_signed_max
= (1 << (howto
->bitsize
- 1)) - 1;
1309 bfd_signed_vma reloc_signed_min
= ~reloc_signed_max
;
1311 bfd_signed_vma signed_check
;
1313 bfd_signed_vma signed_add
;
1315 if (sym_flags
== C_EXT
1316 || sym_flags
== C_STAT
1317 || sym_flags
== C_LABEL
)
1319 elf32_thumb_to_arm_stub (info
, sym_name
, input_bfd
, output_bfd
, input_section
,
1320 hit_data
, sym_sec
, offset
, addend
, value
);
1321 return bfd_reloc_ok
;
1324 relocation
= value
+ addend
;
1325 relocation
-= (input_section
->output_section
->vma
+ input_section
->output_offset
);
1326 relocation
-= offset
;
1328 check
= relocation
>> howto
->rightshift
;
1330 /* If this is a signed value, the rightshift just dropped
1331 leading 1 bits (assuming twos complement). */
1332 if ((bfd_signed_vma
) relocation
>= 0)
1333 signed_check
= check
;
1335 signed_check
= (check
| ((bfd_vma
) - 1 & ~((bfd_vma
) - 1 >> howto
->rightshift
)));
1337 /* Get the value from the object file. */
1338 if (bfd_big_endian (input_bfd
))
1339 add
= (((insn
) & 0x07ff0000) >> 4) | (((insn
) & 0x7ff) << 1);
1341 add
= ((((insn
) & 0x7ff) << 12) | (((insn
) & 0x07ff0000) >> 15));
1343 /* Get the value from the object file with an appropriate sign.
1344 The expression involving howto->src_mask isolates the upper
1345 bit of src_mask. If that bit is set in the value we are
1346 adding, it is negative, and we subtract out that number times
1347 two. If src_mask includes the highest possible bit, then we
1348 can not get the upper bit, but that does not matter since
1349 signed_add needs no adjustment to become negative in that case. */
1353 if ((add
& (((~src_mask
) >> 1) & src_mask
)) != 0)
1354 signed_add
-= (((~src_mask
) >> 1) & src_mask
) << 1;
1356 /* Add the value from the object file, shifted so that it is a
1358 /* howto->bitpos == 0 */
1360 signed_check
+= signed_add
;
1361 relocation
+= signed_add
;
1363 /* Assumes two's complement. */
1364 if (signed_check
> reloc_signed_max
1365 || signed_check
< reloc_signed_min
)
1368 /* Put RELOCATION into the correct bits: */
1370 if (bfd_big_endian (input_bfd
))
1371 relocation
= (((relocation
& 0xffe) >> 1) | ((relocation
<< 4) & 0x07ff0000));
1373 relocation
= (((relocation
& 0xffe) << 15) | ((relocation
>> 12) & 0x7ff));
1375 /* Add RELOCATION to the correct bits of X: */
1376 insn
= ((insn
& ~howto
->dst_mask
) | relocation
);
1378 /* Put the relocated value back in the object file: */
1379 bfd_put_32 (input_bfd
, insn
, hit_data
);
1381 return (overflow
? bfd_reloc_overflow
: bfd_reloc_ok
);
1386 return bfd_reloc_notsupported
;
1388 case R_ARM_AMP_VCALL9
:
1389 return bfd_reloc_notsupported
;
1391 case R_ARM_RSBREL32
:
1392 return bfd_reloc_notsupported
;
1394 case R_ARM_THM_RPC22
:
1395 return bfd_reloc_notsupported
;
1398 return bfd_reloc_notsupported
;
1401 return bfd_reloc_notsupported
;
1404 return bfd_reloc_notsupported
;
1407 return bfd_reloc_notsupported
;
1410 return bfd_reloc_notsupported
;
1413 /* Relocate an ARM ELF section. */
1415 elf32_arm_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
1416 contents
, relocs
, local_syms
, local_sections
)
1418 struct bfd_link_info
*info
;
1420 asection
*input_section
;
1422 Elf_Internal_Rela
*relocs
;
1423 Elf_Internal_Sym
*local_syms
;
1424 asection
**local_sections
;
1426 Elf_Internal_Shdr
*symtab_hdr
;
1427 struct elf_link_hash_entry
**sym_hashes
;
1428 Elf_Internal_Rela
*rel
, *relend
;
1430 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
1431 sym_hashes
= elf_sym_hashes (input_bfd
);
1434 relend
= relocs
+ input_section
->reloc_count
;
1435 for (; rel
< relend
; rel
++)
1438 reloc_howto_type
*howto
;
1439 unsigned long r_symndx
;
1440 Elf_Internal_Sym
*sym
;
1442 struct elf_link_hash_entry
*h
;
1444 bfd_reloc_status_type r
;
1446 r_symndx
= ELF32_R_SYM (rel
->r_info
);
1447 r_type
= ELF32_R_TYPE (rel
->r_info
);
1448 howto
= elf32_arm_howto_table
+ r_type
;
1450 if (info
->relocateable
)
1452 /* This is a relocateable link. We don't have to change
1453 anything, unless the reloc is against a section symbol,
1454 in which case we have to adjust according to where the
1455 section symbol winds up in the output section. */
1456 if (r_symndx
< symtab_hdr
->sh_info
)
1458 sym
= local_syms
+ r_symndx
;
1459 if (ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
1461 sec
= local_sections
[r_symndx
];
1462 rel
->r_addend
+= sec
->output_offset
+ sym
->st_value
;
1469 /* This is a final link. */
1473 if (r_symndx
< symtab_hdr
->sh_info
)
1475 sym
= local_syms
+ r_symndx
;
1476 sec
= local_sections
[r_symndx
];
1477 relocation
= (sec
->output_section
->vma
1478 + sec
->output_offset
1483 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
1484 while (h
->root
.type
== bfd_link_hash_indirect
1485 || h
->root
.type
== bfd_link_hash_warning
)
1486 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
1487 if (h
->root
.type
== bfd_link_hash_defined
1488 || h
->root
.type
== bfd_link_hash_defweak
)
1490 sec
= h
->root
.u
.def
.section
;
1491 relocation
= (h
->root
.u
.def
.value
1492 + sec
->output_section
->vma
1493 + sec
->output_offset
);
1495 else if (h
->root
.type
== bfd_link_hash_undefweak
)
1499 if (!((*info
->callbacks
->undefined_symbol
)
1500 (info
, h
->root
.root
.string
, input_bfd
,
1501 input_section
, rel
->r_offset
)))
1507 r
= elf32_arm_final_link_relocate (howto
, input_bfd
, output_bfd
,
1509 contents
, rel
->r_offset
,
1510 relocation
, rel
->r_addend
,
1511 info
, sec
, (h
? h
->root
.root
.string
: 0),
1512 (h
? h
->other
: sym
->st_other
));
1515 if (r
!= bfd_reloc_ok
)
1518 const char *msg
= (const char *) 0;
1521 name
= h
->root
.root
.string
;
1524 name
= (bfd_elf_string_from_elf_section
1525 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
));
1526 if (name
== NULL
|| *name
== '\0')
1527 name
= bfd_section_name (input_bfd
, sec
);
1532 case bfd_reloc_overflow
:
1533 if (!((*info
->callbacks
->reloc_overflow
)
1534 (info
, name
, howto
->name
, (bfd_vma
) 0,
1535 input_bfd
, input_section
, rel
->r_offset
)))
1539 case bfd_reloc_undefined
:
1540 if (!((*info
->callbacks
->undefined_symbol
)
1541 (info
, name
, input_bfd
, input_section
,
1546 case bfd_reloc_outofrange
:
1547 msg
= _ ("internal error: out of range error");
1550 case bfd_reloc_notsupported
:
1551 msg
= _ ("internal error: unsupported relocation error");
1554 case bfd_reloc_dangerous
:
1555 msg
= _ ("internal error: dangerous error");
1559 msg
= _ ("internal error: unknown error");
1563 if (!((*info
->callbacks
->warning
)
1564 (info
, msg
, name
, input_bfd
, input_section
,
1575 /* Function to keep ARM specific flags in the ELF header. */
1577 elf32_arm_set_private_flags (abfd
, flags
)
1581 if (elf_flags_init (abfd
)
1582 && elf_elfheader (abfd
)->e_flags
!= flags
)
1584 if (flags
& EF_INTERWORK
)
1585 _bfd_error_handler (_ ("\
1586 Warning: Not setting interwork flag of %s since it has already been specified as non-interworking"),
1587 bfd_get_filename (abfd
));
1589 _bfd_error_handler (_ ("\
1590 Warning: Clearing the interwork flag of %s due to outside request"),
1591 bfd_get_filename (abfd
));
1595 elf_elfheader (abfd
)->e_flags
= flags
;
1596 elf_flags_init (abfd
) = true;
1602 /* Copy backend specific data from one object module to another */
1604 elf32_arm_copy_private_bfd_data (ibfd
, obfd
)
1611 if (bfd_get_flavour (ibfd
) != bfd_target_elf_flavour
1612 || bfd_get_flavour (obfd
) != bfd_target_elf_flavour
)
1615 in_flags
= elf_elfheader (ibfd
)->e_flags
;
1616 out_flags
= elf_elfheader (obfd
)->e_flags
;
1618 if (elf_flags_init (obfd
) && in_flags
!= out_flags
)
1620 /* Cannot mix PIC and non-PIC code. */
1621 if ((in_flags
& EF_PIC
) != (out_flags
& EF_PIC
))
1624 /* Cannot mix APCS26 and APCS32 code. */
1625 if ((in_flags
& EF_APCS_26
) != (out_flags
& EF_APCS_26
))
1628 /* Cannot mix float APCS and non-float APCS code. */
1629 if ((in_flags
& EF_APCS_FLOAT
) != (out_flags
& EF_APCS_FLOAT
))
1632 /* If the src and dest have different interworking flags
1633 then turn off the interworking bit. */
1634 if ((in_flags
& EF_INTERWORK
) != (out_flags
& EF_INTERWORK
))
1636 if (out_flags
& EF_INTERWORK
)
1637 _bfd_error_handler (_ ("\
1638 Warning: Clearing the interwork flag in %s because non-interworking code in %s has been linked with it"),
1639 bfd_get_filename (obfd
), bfd_get_filename (ibfd
));
1641 in_flags
&= ~EF_INTERWORK
;
1645 elf_elfheader (obfd
)->e_flags
= in_flags
;
1646 elf_flags_init (obfd
) = true;
1651 /* Merge backend specific data from an object file to the output
1652 object file when linking. */
1654 elf32_arm_merge_private_bfd_data (ibfd
, obfd
)
1661 if (bfd_get_flavour (ibfd
) != bfd_target_elf_flavour
1662 || bfd_get_flavour (obfd
) != bfd_target_elf_flavour
)
1665 /* The input BFD must have had its flags initialised. */
1666 /* The following seems bogus to me -- The flags are initialized in
1667 the assembler but I don't think an elf_flags_init field is
1668 written into the object */
1669 /* BFD_ASSERT (elf_flags_init (ibfd)); */
1671 in_flags
= elf_elfheader (ibfd
)->e_flags
;
1672 out_flags
= elf_elfheader (obfd
)->e_flags
;
1674 if (!elf_flags_init (obfd
))
1676 /* If the input is the default architecture then do not
1677 bother setting the flags for the output architecture,
1678 instead allow future merges to do this. If no future
1679 merges ever set these flags then they will retain their
1680 unitialised values, which surprise surprise, correspond
1681 to the default values. */
1682 if (bfd_get_arch_info (ibfd
)->the_default
)
1685 elf_flags_init (obfd
) = true;
1686 elf_elfheader (obfd
)->e_flags
= in_flags
;
1688 if (bfd_get_arch (obfd
) == bfd_get_arch (ibfd
)
1689 && bfd_get_arch_info (obfd
)->the_default
)
1690 return bfd_set_arch_mach (obfd
, bfd_get_arch (ibfd
), bfd_get_mach (ibfd
));
1695 /* Check flag compatibility. */
1696 if (in_flags
== out_flags
)
1699 /* Complain about various flag mismatches. */
1701 if ((in_flags
& EF_APCS_26
) != (out_flags
& EF_APCS_26
))
1702 _bfd_error_handler (_ ("\
1703 Error: %s compiled for APCS-%d, whereas %s is compiled for APCS-%d"),
1704 bfd_get_filename (ibfd
),
1705 in_flags
& EF_APCS_26
? 26 : 32,
1706 bfd_get_filename (obfd
),
1707 out_flags
& EF_APCS_26
? 26 : 32);
1709 if ((in_flags
& EF_APCS_FLOAT
) != (out_flags
& EF_APCS_FLOAT
))
1710 _bfd_error_handler (_ ("\
1711 Error: %s passes floats in %s registers, whereas %s passes them in %s registers"),
1712 bfd_get_filename (ibfd
),
1713 in_flags
& EF_APCS_FLOAT
? _ ("float") : _ ("integer"),
1714 bfd_get_filename (obfd
),
1715 out_flags
& EF_APCS_26
? _ ("float") : _ ("integer"));
1717 if ((in_flags
& EF_PIC
) != (out_flags
& EF_PIC
))
1718 _bfd_error_handler (_ ("\
1719 Error: %s is compiled as position %s code, whereas %s is not"),
1720 bfd_get_filename (ibfd
),
1721 in_flags
& EF_PIC
? _ ("independent") : _ ("dependent"),
1722 bfd_get_filename (obfd
));
1724 /* Interworking mismatch is only a warning. */
1725 if ((in_flags
& EF_INTERWORK
) != (out_flags
& EF_INTERWORK
))
1727 _bfd_error_handler (_ ("\
1728 Warning: %s %s interworking, whereas %s %s"),
1729 bfd_get_filename (ibfd
),
1730 in_flags
& EF_INTERWORK
? _ ("supports") : _ ("does not support"),
1731 bfd_get_filename (obfd
),
1732 out_flags
& EF_INTERWORK
? _ ("does not") : _ ("does"));
1739 /* Display the flags field */
1741 elf32_arm_print_private_bfd_data (abfd
, ptr
)
1745 FILE *file
= (FILE *) ptr
;
1747 BFD_ASSERT (abfd
!= NULL
&& ptr
!= NULL
);
1749 /* Print normal ELF private data. */
1750 _bfd_elf_print_private_bfd_data (abfd
, ptr
);
1752 /* Ignore init flag - it may not be set, despite the flags field containing valid data. */
1754 /* xgettext:c-format */
1755 fprintf (file
, _ ("private flags = %lx:"), elf_elfheader (abfd
)->e_flags
);
1757 if (elf_elfheader (abfd
)->e_flags
& EF_INTERWORK
)
1758 fprintf (file
, _ (" [interworking enabled]"));
1760 fprintf (file
, _ (" [interworking not enabled]"));
1762 if (elf_elfheader (abfd
)->e_flags
& EF_APCS_26
)
1763 fprintf (file
, _ (" [APCS-26]"));
1765 fprintf (file
, _ (" [APCS-32]"));
1767 if (elf_elfheader (abfd
)->e_flags
& EF_APCS_FLOAT
)
1768 fprintf (file
, _ (" [floats passed in float registers]"));
1770 fprintf (file
, _ (" [floats passed in integer registers]"));
1772 if (elf_elfheader (abfd
)->e_flags
& EF_PIC
)
1773 fprintf (file
, _ (" [position independent]"));
1775 fprintf (file
, _ (" [absolute position]"));
1783 #define TARGET_LITTLE_SYM bfd_elf32_littlearm_vec
1784 #define TARGET_LITTLE_NAME "elf32-littlearm"
1785 #define TARGET_BIG_SYM bfd_elf32_bigarm_vec
1786 #define TARGET_BIG_NAME "elf32-bigarm"
1787 #define ELF_ARCH bfd_arch_arm
1788 #define ELF_MACHINE_CODE EM_ARM
1790 #define bfd_elf32_bfd_reloc_type_lookup elf32_arm_reloc_type_lookup
1791 #define elf_info_to_howto elf32_arm_info_to_howto
1792 #define elf_info_to_howto_rel 0
1793 #define elf_backend_relocate_section elf32_arm_relocate_section
1794 #define bfd_elf32_bfd_copy_private_bfd_data elf32_arm_copy_private_bfd_data
1795 #define bfd_elf32_bfd_merge_private_bfd_data elf32_arm_merge_private_bfd_data
1796 #define bfd_elf32_bfd_set_private_flags elf32_arm_set_private_flags
1797 #define bfd_elf32_bfd_print_private_bfd_data elf32_arm_print_private_bfd_data
1798 #define bfd_elf32_bfd_link_hash_table_create elf32_arm_link_hash_table_create
1800 #define elf_symbol_leading_char '_'
1802 #include "elf32-target.h"
1803 /* end-sanitize-armelf */