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 */
1014 /* Thumb code calling an ARM function */
1016 elf32_thumb_to_arm_stub (info, name, input_bfd, output_bfd, input_section,
1017 hit_data, sym_sec, offset, addend, val)
1018 struct bfd_link_info *info;
1022 asection *input_section;
1031 unsigned long int tmp;
1032 long int ret_offset;
1033 struct elf_link_hash_entry *myh;
1034 struct elf32_arm_link_hash_table *globals;
1036 myh = find_thumb_glue (info, name, input_bfd);
1040 globals = elf32_arm_hash_table (info);
1042 BFD_ASSERT (globals != NULL);
1043 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1045 my_offset = myh->root.u.def.value;
1047 s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
1048 THUMB2ARM_GLUE_SECTION_NAME);
1050 BFD_ASSERT (s != NULL);
1051 BFD_ASSERT (s->contents != NULL);
1052 BFD_ASSERT (s->output_section != NULL);
1054 if ((my_offset & 0x01) == 0x01)
1057 && sym_sec->owner != NULL
1058 && !INTERWORK_FLAG (sym_sec->owner))
1061 (_ ("%s(%s): warning: interworking not enabled."),
1062 bfd_get_filename (sym_sec->owner), name);
1064 (_ (" first occurrence: %s: thumb call to arm"),
1065 bfd_get_filename (input_bfd));
1069 myh->root.u.def.value = my_offset;
1071 bfd_put_16 (output_bfd, t2a1_bx_pc_insn,
1072 s->contents + my_offset);
1074 bfd_put_16 (output_bfd, t2a2_noop_insn,
1075 s->contents + my_offset + 2);
1078 ((bfd_signed_vma) val) /* Address of destination of the stub */
1080 (s->output_offset /* Offset from the start of the current section to the start of the stubs. */
1081 + my_offset /* Offset of the start of this stub from the start of the stubs. */
1082 + s->output_section->vma) /* Address of the start of the current section. */
1083 + 4 /* The branch instruction is 4 bytes into the stub. */
1084 + 8); /* ARM branches work from the pc of the instruction + 8. */
1086 bfd_put_32 (output_bfd,
1087 t2a3_b_insn | ((ret_offset >> 2) & 0x00FFFFFF),
1088 s->contents + my_offset + 4);
1091 BFD_ASSERT (my_offset <= globals->thumb_glue_size);
1093 /* Now go back and fix up the original BL insn to point
1098 - (input_section->output_offset
1102 tmp = bfd_get_32 (input_bfd, hit_data
1103 - input_section->vma);
1105 bfd_put_32 (output_bfd,
1106 insert_thumb_branch (tmp, ret_offset),
1107 hit_data - input_section->vma);
1110 /* Arm code calling a Thumb function */
1112 elf32_arm_to_thumb_stub (info, name, input_bfd, output_bfd, input_section,
1113 hit_data, sym_sec, offset, addend, val)
1115 struct bfd_link_info *info;
1119 asection *input_section;
1126 unsigned long int tmp;
1129 long int ret_offset;
1130 struct elf_link_hash_entry *myh;
1131 struct elf32_arm_link_hash_table *globals;
1133 myh = find_arm_glue (info, name, input_bfd);
1137 globals = elf32_arm_hash_table (info);
1139 BFD_ASSERT (globals != NULL);
1140 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1142 my_offset = myh->root.u.def.value;
1143 s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
1144 ARM2THUMB_GLUE_SECTION_NAME);
1145 BFD_ASSERT (s != NULL);
1146 BFD_ASSERT (s->contents != NULL);
1147 BFD_ASSERT (s->output_section != NULL);
1149 if ((my_offset & 0x01) == 0x01)
1152 && sym_sec->owner != NULL
1153 && !INTERWORK_FLAG (sym_sec->owner))
1156 (_ ("%s(%s): warning: interworking not enabled."),
1157 bfd_get_filename (sym_sec->owner), name);
1159 (_ (" first occurrence: %s: arm call to thumb"),
1160 bfd_get_filename (input_bfd));
1163 myh->root.u.def.value = my_offset;
1165 bfd_put_32 (output_bfd, a2t1_ldr_insn,
1166 s->contents + my_offset);
1168 bfd_put_32 (output_bfd, a2t2_bx_r12_insn,
1169 s->contents + my_offset + 4);
1171 /* It's a thumb address. Add the low order bit. */
1172 bfd_put_32 (output_bfd, val | a2t3_func_addr_insn,
1173 s->contents + my_offset + 8);
1176 BFD_ASSERT (my_offset <= globals->arm_glue_size);
1178 tmp = bfd_get_32 (input_bfd, hit_data);
1179 tmp = tmp & 0xFF000000;
1181 /* Somehow these are both 4 too far, so subtract 8. */
1182 ret_offset = s->output_offset
1184 + s->output_section->vma
1185 - (input_section->output_offset
1186 + input_section->output_section->vma
1190 tmp = tmp | ((ret_offset >> 2) & 0x00FFFFFF);
1192 bfd_put_32 (output_bfd, tmp, hit_data
1193 - input_section->vma);
1197 /* Perform a relocation as part of a final link. */
1198 static bfd_reloc_status_type
1199 elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
1200 input_section, contents, offset, value,
1201 addend, info, sym_sec, sym_name, sym_flags)
1202 reloc_howto_type *howto;
1205 asection *input_section;
1210 struct bfd_link_info *info;
1212 const char *sym_name;
1213 unsigned char sym_flags;
1215 unsigned long r_type = howto->type;
1216 bfd_byte *hit_data = contents + offset;
1222 return bfd_reloc_ok;
1225 /* Arm B/BL instruction */
1227 /* check for arm calling thumb function */
1228 if (sym_flags == C_THUMBSTATFUNC
1229 || sym_flags == C_THUMBEXTFUNC)
1231 elf32_arm_to_thumb_stub (info, sym_name, input_bfd, output_bfd,
1232 input_section, hit_data, sym_sec, offset, addend, value);
1233 return bfd_reloc_ok;
1236 value = value + addend;
1237 value -= (input_section->output_section->vma
1238 + input_section->output_offset + 8);
1240 value = value >> howto->rightshift;
1243 value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);
1244 bfd_put_32 (input_bfd, value, hit_data);
1245 return bfd_reloc_ok;
1249 if (sym_flags == C_THUMBSTATFUNC
1250 || sym_flags == C_THUMBEXTFUNC)
1252 bfd_put_32 (input_bfd, value, hit_data);
1253 return bfd_reloc_ok;
1256 value -= (input_section->output_section->vma
1257 + input_section->output_offset);
1260 bfd_put_32 (input_bfd, value, hit_data);
1261 return bfd_reloc_ok;
1266 if ((long) value > 0x7f || (long) value < -0x80)
1267 return bfd_reloc_overflow;
1269 bfd_put_8 (input_bfd, value, hit_data);
1270 return bfd_reloc_ok;
1275 if ((long) value > 0x7fff || (long) value < -0x8000)
1276 return bfd_reloc_overflow;
1278 bfd_put_16 (input_bfd, value, hit_data);
1279 return bfd_reloc_ok;
1282 /* Support ldr and str instruction for the arm */
1283 /* Also thumb b (unconditional branch) */
1286 if ((long) value > 0x7ff || (long) value < -0x800)
1287 return bfd_reloc_overflow;
1289 value |= (bfd_get_32 (input_bfd, hit_data) & 0xfffff000);
1290 bfd_put_32 (input_bfd, value, hit_data);
1291 return bfd_reloc_ok;
1293 case R_ARM_THM_ABS5:
1294 /* Support ldr and str instructions for the thumb. */
1297 if ((long) value > 0x1f || (long) value < -0x10)
1298 return bfd_reloc_overflow;
1300 value |= bfd_get_16 (input_bfd, hit_data) & 0xf82f;
1301 bfd_put_16 (input_bfd, value, hit_data);
1302 return bfd_reloc_ok;
1305 case R_ARM_THM_PC22:
1306 /* thumb BL (branch long instruction). */
1309 boolean overflow = false;
1310 bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
1311 bfd_vma src_mask = 0x007FFFFE;
1312 bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
1313 bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
1315 bfd_signed_vma signed_check;
1317 bfd_signed_vma signed_add;
1319 if (sym_flags == C_EXT
1320 || sym_flags == C_STAT
1321 || sym_flags == C_LABEL)
1323 elf32_thumb_to_arm_stub (info, sym_name, input_bfd, output_bfd, input_section,
1324 hit_data, sym_sec, offset, addend, value);
1325 return bfd_reloc_ok;
1328 relocation = value + addend;
1329 relocation -= (input_section->output_section->vma + input_section->output_offset);
1330 relocation -= offset;
1332 check = relocation >> howto->rightshift;
1334 /* If this is a signed value, the rightshift just dropped
1335 leading 1 bits (assuming twos complement). */
1336 if ((bfd_signed_vma) relocation >= 0)
1337 signed_check = check;
1339 signed_check = (check | ((bfd_vma) - 1 & ~((bfd_vma) - 1 >> howto->rightshift)));
1341 /* Get the value from the object file. */
1342 if (bfd_big_endian (input_bfd))
1343 add = (((insn) & 0x07ff0000) >> 4) | (((insn) & 0x7ff) << 1);
1345 add = ((((insn) & 0x7ff) << 12) | (((insn) & 0x07ff0000) >> 15));
1347 /* Get the value from the object file with an appropriate sign.
1348 The expression involving howto->src_mask isolates the upper
1349 bit of src_mask. If that bit is set in the value we are
1350 adding, it is negative, and we subtract out that number times
1351 two. If src_mask includes the highest possible bit, then we
1352 can not get the upper bit, but that does not matter since
1353 signed_add needs no adjustment to become negative in that case. */
1357 if ((add & (((~src_mask) >> 1) & src_mask)) != 0)
1358 signed_add -= (((~src_mask) >> 1) & src_mask) << 1;
1360 /* Add the value from the object file, shifted so that it is a
1362 /* howto->bitpos == 0 */
1364 signed_check += signed_add;
1365 relocation += signed_add;
1367 /* Assumes two's complement. */
1368 if (signed_check > reloc_signed_max
1369 || signed_check < reloc_signed_min)
1372 /* Put RELOCATION into the correct bits: */
1374 if (bfd_big_endian (input_bfd))
1375 relocation = (((relocation & 0xffe) >> 1) | ((relocation << 4) & 0x07ff0000));
1377 relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff));
1379 /* Add RELOCATION to the correct bits of X: */
1380 insn = ((insn & ~howto->dst_mask) | relocation);
1382 /* Put the relocated value back in the object file: */
1383 bfd_put_32 (input_bfd, insn, hit_data);
1385 return (overflow ? bfd_reloc_overflow : bfd_reloc_ok);
1390 return bfd_reloc_notsupported;
1392 case R_ARM_AMP_VCALL9:
1393 return bfd_reloc_notsupported;
1395 case R_ARM_RSBREL32:
1396 return bfd_reloc_notsupported;
1398 case R_ARM_THM_RPC22:
1399 return bfd_reloc_notsupported;
1402 return bfd_reloc_notsupported;
1405 return bfd_reloc_notsupported;
1408 return bfd_reloc_notsupported;
1411 return bfd_reloc_notsupported;
1414 return bfd_reloc_notsupported;
1419 /* Relocate an ARM ELF section. */
1421 elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
1422 contents, relocs, local_syms, local_sections)
1424 struct bfd_link_info *info;
1426 asection *input_section;
1428 Elf_Internal_Rela *relocs;
1429 Elf_Internal_Sym *local_syms;
1430 asection **local_sections;
1432 Elf_Internal_Shdr *symtab_hdr;
1433 struct elf_link_hash_entry **sym_hashes;
1434 Elf_Internal_Rela *rel, *relend;
1437 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1438 sym_hashes = elf_sym_hashes (input_bfd);
1441 relend = relocs + input_section->reloc_count;
1442 for (; rel < relend; rel++)
1445 reloc_howto_type *howto;
1446 unsigned long r_symndx;
1447 Elf_Internal_Sym *sym;
1449 struct elf_link_hash_entry *h;
1451 bfd_reloc_status_type r;
1453 r_symndx = ELF32_R_SYM (rel->r_info);
1454 r_type = ELF32_R_TYPE (rel->r_info);
1455 howto = elf32_arm_howto_table + r_type;
1457 if (info->relocateable)
1459 /* This is a relocateable link. We don't have to change
1460 anything, unless the reloc is against a section symbol,
1461 in which case we have to adjust according to where the
1462 section symbol winds up in the output section. */
1463 if (r_symndx < symtab_hdr->sh_info)
1465 sym = local_syms + r_symndx;
1466 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
1468 sec = local_sections[r_symndx];
1469 rel->r_addend += sec->output_offset + sym->st_value;
1476 /* This is a final link. */
1480 if (r_symndx < symtab_hdr->sh_info)
1482 sym = local_syms + r_symndx;
1483 sec = local_sections[r_symndx];
1484 relocation = (sec->output_section->vma
1485 + sec->output_offset
1490 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
1491 while (h->root.type == bfd_link_hash_indirect
1492 || h->root.type == bfd_link_hash_warning)
1493 h = (struct elf_link_hash_entry *) h->root.u.i.link;
1494 if (h->root.type == bfd_link_hash_defined
1495 || h->root.type == bfd_link_hash_defweak)
1497 sec = h->root.u.def.section;
1498 relocation = (h->root.u.def.value
1499 + sec->output_section->vma
1500 + sec->output_offset);
1502 else if (h->root.type == bfd_link_hash_undefweak)
1506 if (!((*info->callbacks->undefined_symbol)
1507 (info, h->root.root.string, input_bfd,
1508 input_section, rel->r_offset)))
1515 name = h->root.root.string;
1518 name = (bfd_elf_string_from_elf_section
1519 (input_bfd, symtab_hdr->sh_link, sym->st_name));
1520 if (name == NULL || *name == '\0')
1521 name = bfd_section_name (input_bfd, sec);
1524 r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
1526 contents, rel->r_offset,
1527 relocation, rel->r_addend,
1529 (h ? h->other : sym->st_other));
1532 if (r != bfd_reloc_ok)
1534 const char *msg = (const char *) 0;
1538 case bfd_reloc_overflow:
1539 if (!((*info->callbacks->reloc_overflow)
1540 (info, name, howto->name, (bfd_vma) 0,
1541 input_bfd, input_section, rel->r_offset)))
1545 case bfd_reloc_undefined:
1546 if (!((*info->callbacks->undefined_symbol)
1547 (info, name, input_bfd, input_section,
1552 case bfd_reloc_outofrange:
1553 msg = _ ("internal error: out of range error");
1556 case bfd_reloc_notsupported:
1557 msg = _ ("internal error: unsupported relocation error");
1560 case bfd_reloc_dangerous:
1561 msg = _ ("internal error: dangerous error");
1565 msg = _ ("internal error: unknown error");
1569 if (!((*info->callbacks->warning)
1570 (info, msg, name, input_bfd, input_section,
1581 /* Function to keep ARM specific flags in the ELF header. */
1583 elf32_arm_set_private_flags (abfd, flags)
1587 if (elf_flags_init (abfd)
1588 && elf_elfheader (abfd)->e_flags != flags)
1590 if (flags & EF_INTERWORK)
1591 _bfd_error_handler (_ ("\
1592 Warning: Not setting interwork flag of %s since it has already been specified as non-interworking"),
1593 bfd_get_filename (abfd));
1595 _bfd_error_handler (_ ("\
1596 Warning: Clearing the interwork flag of %s due to outside request"),
1597 bfd_get_filename (abfd));
1601 elf_elfheader (abfd)->e_flags = flags;
1602 elf_flags_init (abfd) = true;
1608 /* Copy backend specific data from one object module to another */
1610 elf32_arm_copy_private_bfd_data (ibfd, obfd)
1617 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1618 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1621 in_flags = elf_elfheader (ibfd)->e_flags;
1622 out_flags = elf_elfheader (obfd)->e_flags;
1624 if (elf_flags_init (obfd) && in_flags != out_flags)
1626 /* Cannot mix PIC and non-PIC code. */
1627 if ((in_flags & EF_PIC) != (out_flags & EF_PIC))
1630 /* Cannot mix APCS26 and APCS32 code. */
1631 if ((in_flags & EF_APCS_26) != (out_flags & EF_APCS_26))
1634 /* Cannot mix float APCS and non-float APCS code. */
1635 if ((in_flags & EF_APCS_FLOAT) != (out_flags & EF_APCS_FLOAT))
1638 /* If the src and dest have different interworking flags
1639 then turn off the interworking bit. */
1640 if ((in_flags & EF_INTERWORK) != (out_flags & EF_INTERWORK))
1642 if (out_flags & EF_INTERWORK)
1643 _bfd_error_handler (_ ("\
1644 Warning: Clearing the interwork flag in %s because non-interworking code in %s has been linked with it"),
1645 bfd_get_filename (obfd), bfd_get_filename (ibfd));
1647 in_flags &= ~EF_INTERWORK;
1651 elf_elfheader (obfd)->e_flags = in_flags;
1652 elf_flags_init (obfd) = true;
1657 /* Merge backend specific data from an object file to the output
1658 object file when linking. */
1660 elf32_arm_merge_private_bfd_data (ibfd, obfd)
1667 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1668 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1671 /* The input BFD must have had its flags initialised. */
1672 /* The following seems bogus to me -- The flags are initialized in
1673 the assembler but I don't think an elf_flags_init field is
1674 written into the object */
1675 /* BFD_ASSERT (elf_flags_init (ibfd)); */
1677 in_flags = elf_elfheader (ibfd)->e_flags;
1678 out_flags = elf_elfheader (obfd)->e_flags;
1680 if (!elf_flags_init (obfd))
1682 /* If the input is the default architecture then do not
1683 bother setting the flags for the output architecture,
1684 instead allow future merges to do this. If no future
1685 merges ever set these flags then they will retain their
1686 unitialised values, which surprise surprise, correspond
1687 to the default values. */
1688 if (bfd_get_arch_info (ibfd)->the_default)
1691 elf_flags_init (obfd) = true;
1692 elf_elfheader (obfd)->e_flags = in_flags;
1694 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
1695 && bfd_get_arch_info (obfd)->the_default)
1696 return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
1701 /* Check flag compatibility. */
1702 if (in_flags == out_flags)
1705 /* Complain about various flag mismatches. */
1707 if ((in_flags & EF_APCS_26) != (out_flags & EF_APCS_26))
1708 _bfd_error_handler (_ ("\
1709 Error: %s compiled for APCS-%d, whereas %s is compiled for APCS-%d"),
1710 bfd_get_filename (ibfd),
1711 in_flags & EF_APCS_26 ? 26 : 32,
1712 bfd_get_filename (obfd),
1713 out_flags & EF_APCS_26 ? 26 : 32);
1715 if ((in_flags & EF_APCS_FLOAT) != (out_flags & EF_APCS_FLOAT))
1716 _bfd_error_handler (_ ("\
1717 Error: %s passes floats in %s registers, whereas %s passes them in %s registers"),
1718 bfd_get_filename (ibfd),
1719 in_flags & EF_APCS_FLOAT ? _ ("float") : _ ("integer"),
1720 bfd_get_filename (obfd),
1721 out_flags & EF_APCS_26 ? _ ("float") : _ ("integer"));
1723 if ((in_flags & EF_PIC) != (out_flags & EF_PIC))
1724 _bfd_error_handler (_ ("\
1725 Error: %s is compiled as position %s code, whereas %s is not"),
1726 bfd_get_filename (ibfd),
1727 in_flags & EF_PIC ? _ ("independent") : _ ("dependent"),
1728 bfd_get_filename (obfd));
1730 /* Interworking mismatch is only a warning. */
1731 if ((in_flags & EF_INTERWORK) != (out_flags & EF_INTERWORK))
1733 _bfd_error_handler (_ ("\
1734 Warning: %s %s interworking, whereas %s %s"),
1735 bfd_get_filename (ibfd),
1736 in_flags & EF_INTERWORK ? _ ("supports") : _ ("does not support"),
1737 bfd_get_filename (obfd),
1738 out_flags & EF_INTERWORK ? _ ("does not") : _ ("does"));
1745 /* Display the flags field */
1747 elf32_arm_print_private_bfd_data (abfd, ptr)
1751 FILE *file = (FILE *) ptr;
1753 BFD_ASSERT (abfd != NULL && ptr != NULL);
1755 /* Print normal ELF private data. */
1756 _bfd_elf_print_private_bfd_data (abfd, ptr);
1758 /* Ignore init flag - it may not be set, despite the flags field containing valid data. */
1760 /* xgettext:c-format */
1761 fprintf (file, _ ("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
1763 if (elf_elfheader (abfd)->e_flags & EF_INTERWORK)
1764 fprintf (file, _ (" [interworking enabled]"));
1766 fprintf (file, _ (" [interworking not enabled]"));
1768 if (elf_elfheader (abfd)->e_flags & EF_APCS_26)
1769 fprintf (file, _ (" [APCS-26]"));
1771 fprintf (file, _ (" [APCS-32]"));
1773 if (elf_elfheader (abfd)->e_flags & EF_APCS_FLOAT)
1774 fprintf (file, _ (" [floats passed in float registers]"));
1776 fprintf (file, _ (" [floats passed in integer registers]"));
1778 if (elf_elfheader (abfd)->e_flags & EF_PIC)
1779 fprintf (file, _ (" [position independent]"));
1781 fprintf (file, _ (" [absolute position]"));
1789 #define TARGET_LITTLE_SYM bfd_elf32_littlearm_vec
1790 #define TARGET_LITTLE_NAME "elf32-littlearm"
1791 #define TARGET_BIG_SYM bfd_elf32_bigarm_vec
1792 #define TARGET_BIG_NAME "elf32-bigarm"
1793 #define ELF_ARCH bfd_arch_arm
1794 #define ELF_MACHINE_CODE EM_ARM
1796 #define bfd_elf32_bfd_reloc_type_lookup elf32_arm_reloc_type_lookup
1797 #define elf_info_to_howto elf32_arm_info_to_howto
1798 #define elf_info_to_howto_rel 0
1799 #define elf_backend_relocate_section elf32_arm_relocate_section
1800 #define bfd_elf32_bfd_copy_private_bfd_data elf32_arm_copy_private_bfd_data
1801 #define bfd_elf32_bfd_merge_private_bfd_data elf32_arm_merge_private_bfd_data
1802 #define bfd_elf32_bfd_set_private_flags elf32_arm_set_private_flags
1803 #define bfd_elf32_bfd_print_private_bfd_data elf32_arm_print_private_bfd_data
1804 #define bfd_elf32_bfd_link_hash_table_create elf32_arm_link_hash_table_create
1806 #define elf_symbol_leading_char '_'
1808 #include "elf32-target.h"
1809 /* end-sanitize-armelf */