* elfxx-target.h (USE_REL): Don't define as 1.
[deliverable/binutils-gdb.git] / bfd / elf32-arm.h
index d5cfcd428f62925f6965a1e16c8a8c316c31091b..5901aeaa090c54214851286280afb3cd4a41754e 100644 (file)
@@ -1,5 +1,5 @@
 /* 32-bit ELF support for ARM
-   Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+#ifndef USE_REL
+#define USE_REL        0
+#endif
+
 typedef unsigned long int insn32;
 typedef unsigned short int insn16;
 
@@ -42,10 +46,6 @@ static struct elf_link_hash_entry *find_thumb_glue
   PARAMS ((struct bfd_link_info *, const char *, bfd *));
 static struct elf_link_hash_entry *find_arm_glue
   PARAMS ((struct bfd_link_info *, const char *, bfd *));
-static void record_arm_to_thumb_glue
-  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
-static void record_thumb_to_arm_glue
-  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
 static void elf32_arm_post_process_headers
   PARAMS ((bfd *, struct bfd_link_info *));
 static int elf32_arm_to_thumb_stub
@@ -58,7 +58,7 @@ static boolean elf32_arm_relocate_section
   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
           Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
 static asection * elf32_arm_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean elf32_arm_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
@@ -80,19 +80,26 @@ static boolean elf32_arm_finish_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 static struct bfd_hash_entry * elf32_arm_link_hash_newfunc
   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-#ifdef USE_REL
+#if USE_REL
 static void arm_add_to_rel
   PARAMS ((bfd *, bfd_byte *, reloc_howto_type *, bfd_signed_vma));
 #endif
+static enum elf_reloc_type_class elf32_arm_reloc_type_class
+  PARAMS ((const Elf_Internal_Rela *));
 
+#ifndef ELFARM_NABI_C_INCLUDED
+static void record_arm_to_thumb_glue
+  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
+static void record_thumb_to_arm_glue
+  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
 boolean bfd_elf32_arm_allocate_interworking_sections
   PARAMS ((struct bfd_link_info *));
 boolean bfd_elf32_arm_get_bfd_for_interworking
   PARAMS ((bfd *, struct bfd_link_info *));
 boolean bfd_elf32_arm_process_before_allocation
   PARAMS ((bfd *, struct bfd_link_info *, int));
-static enum elf_reloc_type_class elf32_arm_reloc_type_class
-  PARAMS ((const Elf_Internal_Rela *));
+#endif
+
 
 #define INTERWORK_FLAG(abfd)   (elf_elfheader (abfd)->e_flags & EF_ARM_INTERWORK)
 
@@ -236,14 +243,14 @@ elf32_arm_link_hash_table_create (abfd)
   struct elf32_arm_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct elf32_arm_link_hash_table);
 
-  ret = (struct elf32_arm_link_hash_table *) bfd_alloc (abfd, amt);
+  ret = (struct elf32_arm_link_hash_table *) bfd_malloc (amt);
   if (ret == (struct elf32_arm_link_hash_table *) NULL)
     return NULL;
 
   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
                                      elf32_arm_link_hash_newfunc))
     {
-      bfd_release (abfd, ret);
+      free (ret);
       return NULL;
     }
 
@@ -367,6 +374,7 @@ static const insn16 t2a4_bx_insn = 0x4730;
 static const insn32 t2a5_pop_insn = 0xe8bd4040;
 static const insn32 t2a6_bx_insn = 0xe12fff1e;
 
+#ifndef ELFARM_NABI_C_INCLUDED
 boolean
 bfd_elf32_arm_allocate_interworking_sections (info)
      struct bfd_link_info * info;
@@ -423,6 +431,7 @@ record_arm_to_thumb_glue (link_info, h)
   asection * s;
   char * tmp_name;
   struct elf_link_hash_entry * myh;
+  struct bfd_link_hash_entry * bh;
   struct elf32_arm_link_hash_table * globals;
   bfd_vma val;
 
@@ -456,11 +465,11 @@ record_arm_to_thumb_glue (link_info, h)
   /* The only trick here is using hash_table->arm_glue_size as the value. Even
      though the section isn't allocated yet, this is where we will be putting
      it.  */
+  bh = NULL;
   val = globals->arm_glue_size + 1;
   _bfd_generic_link_add_one_symbol (link_info, globals->bfd_of_glue_owner,
                                    tmp_name, BSF_GLOBAL, s, val,
-                                   NULL, true, false,
-                                   (struct bfd_link_hash_entry **) &myh);
+                                   NULL, true, false, &bh);
 
   free (tmp_name);
 
@@ -478,6 +487,7 @@ record_thumb_to_arm_glue (link_info, h)
   asection *s;
   char *tmp_name;
   struct elf_link_hash_entry *myh;
+  struct bfd_link_hash_entry *bh;
   struct elf32_arm_link_hash_table *hash_table;
   char bind;
   bfd_vma val;
@@ -509,13 +519,14 @@ record_thumb_to_arm_glue (link_info, h)
       return;
     }
 
+  bh = NULL;
   val = hash_table->thumb_glue_size + 1;
   _bfd_generic_link_add_one_symbol (link_info, hash_table->bfd_of_glue_owner,
                                    tmp_name, BSF_GLOBAL, s, val,
-                                   NULL, true, false,
-                                   (struct bfd_link_hash_entry **) &myh);
+                                   NULL, true, false, &bh);
 
   /* If we mark it 'Thumb', the disassembler will do a better job.  */
+  myh = (struct elf_link_hash_entry *) bh;
   bind = ELF_ST_BIND (myh->type);
   myh->type = ELF_ST_INFO (bind, STT_ARM_TFUNC);
 
@@ -532,13 +543,11 @@ record_thumb_to_arm_glue (link_info, h)
 
   sprintf (tmp_name, CHANGE_TO_ARM, name);
 
-  myh = NULL;
-
+  bh = NULL;
   val = hash_table->thumb_glue_size + 4,
   _bfd_generic_link_add_one_symbol (link_info, hash_table->bfd_of_glue_owner,
                                    tmp_name, BSF_LOCAL, s, val,
-                                   NULL, true, false,
-                                   (struct bfd_link_hash_entry **) &myh);
+                                   NULL, true, false, &bh);
 
   free (tmp_name);
 
@@ -547,31 +556,22 @@ record_thumb_to_arm_glue (link_info, h)
   return;
 }
 
-/* Select a BFD to be used to hold the sections used by the glue code.
-   This function is called from the linker scripts in ld/emultempl/
-   {armelf/pe}.em  */
+/* Add the glue sections to ABFD.  This function is called from the
+   linker scripts in ld/emultempl/{armelf}.em.  */
 
 boolean
-bfd_elf32_arm_get_bfd_for_interworking (abfd, info)
+bfd_elf32_arm_add_glue_sections_to_bfd (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
 {
-  struct elf32_arm_link_hash_table *globals;
   flagword flags;
   asection *sec;
 
-  /* If we are only performing a partial link do not bother
-     getting a bfd to hold the glue.  */
+  /* If we are only performing a partial
+     link do not bother adding the glue.  */
   if (info->relocateable)
     return true;
 
-  globals = elf32_arm_hash_table (info);
-
-  BFD_ASSERT (globals != NULL);
-
-  if (globals->bfd_of_glue_owner != NULL)
-    return true;
-
   sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME);
 
   if (sec == NULL)
@@ -609,6 +609,32 @@ bfd_elf32_arm_get_bfd_for_interworking (abfd, info)
       sec->gc_mark = 1;
     }
 
+  return true;
+}
+
+/* Select a BFD to be used to hold the sections used by the glue code.
+   This function is called from the linker scripts in ld/emultempl/
+   {armelf/pe}.em  */
+
+boolean
+bfd_elf32_arm_get_bfd_for_interworking (abfd, info)
+     bfd *abfd;
+     struct bfd_link_info *info;
+{
+  struct elf32_arm_link_hash_table *globals;
+
+  /* If we are only performing a partial link
+     do not bother getting a bfd to hold the glue.  */
+  if (info->relocateable)
+    return true;
+
+  globals = elf32_arm_hash_table (info);
+
+  BFD_ASSERT (globals != NULL);
+
+  if (globals->bfd_of_glue_owner != NULL)
+    return true;
+
   /* Save the bfd for later use.  */
   globals->bfd_of_glue_owner = abfd;
 
@@ -622,12 +648,9 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
      int no_pipeline_knowledge;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Rela *free_relocs = NULL;
+  Elf_Internal_Rela *internal_relocs = NULL;
   Elf_Internal_Rela *irel, *irelend;
   bfd_byte *contents = NULL;
-  bfd_byte *free_contents = NULL;
-  Elf32_External_Sym *extsyms = NULL;
-  Elf32_External_Sym *free_extsyms = NULL;
 
   asection *sec;
   struct elf32_arm_link_hash_table *globals;
@@ -660,13 +683,15 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
       symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 
       /* Load the relocs.  */
-      irel = (_bfd_elf32_link_read_relocs (abfd, sec, (PTR) NULL,
-                                          (Elf_Internal_Rela *) NULL, false));
+      internal_relocs
+       = _bfd_elf32_link_read_relocs (abfd, sec, (PTR) NULL,
+                                      (Elf_Internal_Rela *) NULL, false);
 
-      BFD_ASSERT (irel != 0);
+      if (internal_relocs == NULL)
+       goto error_return;
 
-      irelend = irel + sec->reloc_count;
-      for (; irel < irelend; irel++)
+      irelend = internal_relocs + sec->reloc_count;
+      for (irel = internal_relocs; irel < irelend; irel++)
        {
          long r_type;
          unsigned long r_index;
@@ -694,37 +719,12 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
                  if (contents == NULL)
                    goto error_return;
 
-                 free_contents = contents;
-
                  if (!bfd_get_section_contents (abfd, sec, contents,
                                                 (file_ptr) 0, sec->_raw_size))
                    goto error_return;
                }
            }
 
-         /* Read this BFD's symbols if we haven't done so already.  */
-         if (extsyms == NULL)
-           {
-             /* Get cached copy if it exists.  */
-             if (symtab_hdr->contents != NULL)
-               extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-             else
-               {
-                 /* Go get them off disk.  */
-                 extsyms = ((Elf32_External_Sym *)
-                            bfd_malloc (symtab_hdr->sh_size));
-                 if (extsyms == NULL)
-                   goto error_return;
-
-                 free_extsyms = extsyms;
-
-                 if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-                     || (bfd_bread (extsyms, symtab_hdr->sh_size, abfd)
-                         != symtab_hdr->sh_size))
-                   goto error_return;
-               }
-           }
-
          /* If the relocation is not against a symbol it cannot concern us.  */
          h = NULL;
 
@@ -764,20 +764,31 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
              break;
            }
        }
+
+      if (contents != NULL
+         && elf_section_data (sec)->this_hdr.contents != contents)
+       free (contents);
+      contents = NULL;
+
+      if (internal_relocs != NULL
+         && elf_section_data (sec)->relocs != internal_relocs)
+       free (internal_relocs);
+      internal_relocs = NULL;
     }
 
   return true;
 
 error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-  if (free_contents != NULL)
-    free (free_contents);
-  if (free_extsyms != NULL)
-    free (free_extsyms);
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
+    free (contents);
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
 
   return false;
 }
+#endif
 
 /* The thumb form of a long branch is a bit finicky, because the offset
    encoding is split over two fields, each in it's own instruction. They
@@ -1087,7 +1098,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
   local_got_offsets = elf_local_got_offsets (input_bfd);
   r_symndx = ELF32_R_SYM (rel->r_info);
 
-#ifdef USE_REL
+#if USE_REL
   addend = bfd_get_32 (input_bfd, hit_data) & howto->src_mask;
 
   if (addend & ((howto->src_mask + 1) >> 1))
@@ -1148,26 +1159,24 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
            }
 
          skip = false;
+         relocate = false;
 
          outrel.r_offset =
            _bfd_elf_section_offset (output_bfd, info, input_section,
                                     rel->r_offset);
          if (outrel.r_offset == (bfd_vma) -1)
            skip = true;
+         else if (outrel.r_offset == (bfd_vma) -2)
+           skip = true, relocate = true;
          outrel.r_offset += (input_section->output_section->vma
                              + input_section->output_offset);
 
          if (skip)
-           {
-             memset (&outrel, 0, sizeof outrel);
-             relocate = false;
-           }
+           memset (&outrel, 0, sizeof outrel);
          else if (r_type == R_ARM_PC24)
            {
              BFD_ASSERT (h != NULL && h->dynindx != -1);
-             if ((input_section->flags & SEC_ALLOC) != 0)
-               relocate = false;
-             else
+             if ((input_section->flags & SEC_ALLOC) == 0)
                relocate = true;
              outrel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_PC24);
            }
@@ -1184,9 +1193,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
              else
                {
                  BFD_ASSERT (h->dynindx != -1);
-                 if ((input_section->flags & SEC_ALLOC) != 0)
-                   relocate = false;
-                 else
+                 if ((input_section->flags & SEC_ALLOC) == 0)
                    relocate = true;
                  outrel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_ABS32);
                }
@@ -1367,7 +1374,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
 
     case R_ARM_THM_ABS5:
       /* Support ldr and str instructions for the thumb.  */
-#ifdef USE_REL
+#if USE_REL
       /* Need to refetch addend.  */
       addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask;
       /* ??? Need to determine shift amount from operand size.  */
@@ -1394,12 +1401,12 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
        boolean        overflow = false;
        bfd_vma        upper_insn = bfd_get_16 (input_bfd, hit_data);
        bfd_vma        lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
-       bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
+       bfd_signed_vma reloc_signed_max = ((1 << (howto->bitsize - 1)) - 1) >> howto->rightshift;
        bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
        bfd_vma        check;
        bfd_signed_vma signed_check;
 
-#ifdef USE_REL
+#if USE_REL
        /* Need to refetch the addend and squish the two 11 bit pieces
           together.  */
        {
@@ -1475,22 +1482,19 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
        if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
          overflow = true;
 
-       /* Put RELOCATION back into the insn.  */
-       upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff);
-       lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff);
-
 #ifndef OLD_ARM_ABI
        if (r_type == R_ARM_THM_XPC22
            && ((lower_insn & 0x1800) == 0x0800))
-         /* Remove bit zero of the adjusted offset.  Bit zero can only be
-            set if the upper insn is at a half-word boundary, since the
-            destination address, an ARM instruction, must always be on a
-            word boundary.  The semantics of the BLX (1) instruction, however,
-            are that bit zero in the offset must always be zero, and the
-            corresponding bit one in the target address will be set from bit
-            one of the source address.  */
-         lower_insn &= ~1;
+         /* For a BLX instruction, make sure that the relocation is rounded up
+            to a word boundary.  This follows the semantics of the instruction
+            which specifies that bit 1 of the target address will come from bit
+            1 of the base address.  */
+         relocation = (relocation + 2) & ~ 3;
 #endif
+       /* Put RELOCATION back into the insn.  */
+       upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff);
+       lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff);
+
        /* Put the relocated value back in the object file:  */
        bfd_put_16 (input_bfd, upper_insn, hit_data);
        bfd_put_16 (input_bfd, lower_insn, hit_data + 2);
@@ -1499,6 +1503,50 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
       }
       break;
 
+    case R_ARM_THM_PC11:
+      /* Thumb B (branch) instruction).  */
+      {
+       bfd_signed_vma relocation;
+       bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
+       bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
+       bfd_signed_vma signed_check;
+
+#if USE_REL
+       /* Need to refetch addend.  */
+       addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask;
+       if (addend & ((howto->src_mask + 1) >> 1))
+         {
+           signed_addend = -1;
+           signed_addend &= ~ howto->src_mask;
+           signed_addend |= addend;
+         }
+       else
+         signed_addend = addend;
+       /* The value in the insn has been right shifted.  We need to
+          undo this, so that we can perform the address calculation
+          in terms of bytes.  */
+       signed_addend <<= howto->rightshift;
+#endif
+       relocation = value + signed_addend;
+
+       relocation -= (input_section->output_section->vma
+                      + input_section->output_offset
+                      + rel->r_offset);
+
+       relocation >>= howto->rightshift;
+       signed_check = relocation;
+       relocation &= howto->dst_mask;
+       relocation |= (bfd_get_16 (input_bfd, hit_data) & (~ howto->dst_mask));
+
+       bfd_put_16 (input_bfd, relocation, hit_data);
+
+       /* Assumes two's complement.  */
+       if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
+         return bfd_reloc_overflow;
+
+       return bfd_reloc_ok;
+      }
+
     case R_ARM_GNU_VTINHERIT:
     case R_ARM_GNU_VTENTRY:
       return bfd_reloc_ok;
@@ -1523,6 +1571,12 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
       if (sgot == NULL)
         return bfd_reloc_notsupported;
 
+      /* If we are addressing a Thumb function, we need to adjust the
+        address by one, so that attempts to call the function pointer will
+        correctly interpret it as Thumb code.  */
+      if (sym_flags == STT_ARM_TFUNC)
+       value += 1;
+
       /* Note that sgot->output_offset is not involved in this
          calculation.  We always want the start of .got.  If we
          define _GLOBAL_OFFSET_TABLE in a different way, as is
@@ -1575,6 +1629,13 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
                off &= ~1;
              else
                {
+                 /* If we are addressing a Thumb function, we need to
+                    adjust the address by one, so that attempts to
+                    call the function pointer will correctly
+                    interpret it as Thumb code.  */
+                 if (sym_flags == STT_ARM_TFUNC)
+                   value |= 1;
+
                  bfd_put_32 (output_bfd, value, sgot->contents + off);
                  h->got.offset |= 1;
                }
@@ -1688,7 +1749,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
     }
 }
 
-#ifdef USE_REL
+#if USE_REL
 /* Add INCREMENT to the reloc (of type HOWTO) at ADDRESS.  */
 static void
 arm_add_to_rel (abfd, address, howto, increment)
@@ -1780,6 +1841,11 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
   Elf_Internal_Rela *           relend;
   const char *                  name;
 
+#if !USE_REL
+  if (info->relocateable)
+    return true;
+#endif
+
   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
 
@@ -1804,7 +1870,7 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
           || r_type == R_ARM_GNU_VTINHERIT)
         continue;
 
-#ifdef USE_REL
+#if USE_REL
       elf32_arm_info_to_howto (input_bfd, & bfd_reloc,
                               (Elf_Internal_Rel *) rel);
 #else
@@ -1812,6 +1878,7 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
 #endif
       howto = bfd_reloc.howto;
 
+#if USE_REL
       if (info->relocateable)
        {
          /* This is a relocateable link.  We don't have to change
@@ -1824,19 +1891,16 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
              if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
                {
                  sec = local_sections[r_symndx];
-#ifdef USE_REL
                  arm_add_to_rel (input_bfd, contents + rel->r_offset,
                                  howto,
                                  (bfd_signed_vma) (sec->output_offset
                                                    + sym->st_value));
-#else
-                 rel->r_addend += (sec->output_offset + sym->st_value);
-#endif
                }
            }
 
          continue;
        }
+#endif
 
       /* This is a final link.  */
       h = NULL;
@@ -1847,7 +1911,7 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
        {
          sym = local_syms + r_symndx;
          sec = local_sections[r_symndx];
-#ifdef USE_REL
+#if USE_REL
          relocation = (sec->output_section->vma
                        + sec->output_offset
                        + sym->st_value);
@@ -2071,11 +2135,11 @@ elf32_arm_set_private_flags (abfd, flags)
        {
          if (flags & EF_ARM_INTERWORK)
            (*_bfd_error_handler) (_("\
-Warning: Not setting interwork flag of %s since it has already been specified as non-interworking"),
+Warning: Not setting interworking flag of %s since it has already been specified as non-interworking"),
                                   bfd_archive_filename (abfd));
          else
            _bfd_error_handler (_("\
-Warning: Clearing the interwork flag of %s due to outside request"),
+Warning: Clearing the interworking flag of %s due to outside request"),
                                bfd_archive_filename (abfd));
        }
     }
@@ -2123,7 +2187,7 @@ elf32_arm_copy_private_bfd_data (ibfd, obfd)
        {
          if (out_flags & EF_ARM_INTERWORK)
            _bfd_error_handler (_("\
-Warning: Clearing the interwork flag in %s because non-interworking code in %s has been linked with it"),
+Warning: Clearing the interworking flag of %s because non-interworking code in %s has been linked with it"),
                                bfd_get_filename (obfd),
                                bfd_archive_filename (ibfd));
 
@@ -2156,7 +2220,7 @@ elf32_arm_merge_private_bfd_data (ibfd, obfd)
   asection *sec;
 
   /* Check if we have the same endianess.  */
-  if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
+  if (! _bfd_generic_verify_endian_match (ibfd, obfd))
     return false;
 
   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
@@ -2218,7 +2282,7 @@ elf32_arm_merge_private_bfd_data (ibfd, obfd)
   if (EF_ARM_EABI_VERSION (in_flags) != EF_ARM_EABI_VERSION (out_flags))
     {
       _bfd_error_handler (_("\
-Error: %s compiled for EABI version %d, whereas %s is compiled for version %d"),
+ERROR: %s is compiled for EABI version %d, whereas %s is compiled for version %d"),
                          bfd_archive_filename (ibfd),
                          (in_flags & EF_ARM_EABIMASK) >> 24,
                          bfd_get_filename (obfd),
@@ -2232,7 +2296,7 @@ Error: %s compiled for EABI version %d, whereas %s is compiled for version %d"),
       if ((in_flags & EF_ARM_APCS_26) != (out_flags & EF_ARM_APCS_26))
        {
          _bfd_error_handler (_("\
-Error: %s compiled for APCS-%d, whereas %s is compiled for APCS-%d"),
+ERROR: %s is compiled for APCS-%d, whereas target %s uses APCS-%d"),
                              bfd_archive_filename (ibfd),
                              in_flags & EF_ARM_APCS_26 ? 26 : 32,
                              bfd_get_filename (obfd),
@@ -2242,27 +2306,60 @@ Error: %s compiled for APCS-%d, whereas %s is compiled for APCS-%d"),
 
       if ((in_flags & EF_ARM_APCS_FLOAT) != (out_flags & EF_ARM_APCS_FLOAT))
        {
-         char *s1 = in_flags  & EF_ARM_APCS_FLOAT ? _("float") : _("integer");
-         char *s2 = out_flags & EF_ARM_APCS_FLOAT ? _("float") : _("integer");
+         if (in_flags & EF_ARM_APCS_FLOAT)
+           _bfd_error_handler (_("\
+ERROR: %s passes floats in float registers, whereas %s passes them in integer registers"),
+                               bfd_archive_filename (ibfd),
+                               bfd_get_filename (obfd));
+         else
+           _bfd_error_handler (_("\
+ERROR: %s passes floats in integer registers, whereas %s passes them in float registers"),
+                               bfd_archive_filename (ibfd),
+                               bfd_get_filename (obfd));
+
+         flags_compatible = false;
+       }
+
+      if ((in_flags & EF_ARM_VFP_FLOAT) != (out_flags & EF_ARM_VFP_FLOAT))
+       {
+         if (in_flags & EF_ARM_VFP_FLOAT)
+           _bfd_error_handler (_("\
+ERROR: %s uses VFP instructions, whereas %s uses FPA instructions"),
+                               bfd_archive_filename (ibfd),
+                               bfd_get_filename (obfd));
+         else
+           _bfd_error_handler (_("\
+ERROR: %s uses FPA instructions, whereas %s uses VFP instructions"),
+                               bfd_archive_filename (ibfd),
+                               bfd_get_filename (obfd));
 
-         _bfd_error_handler (_("\
-Error: %s passes floats in %s registers, whereas %s passes them in %s registers"),
-                             bfd_archive_filename (ibfd), s1,
-                             bfd_get_filename (obfd), s2);
          flags_compatible = false;
        }
 
 #ifdef EF_ARM_SOFT_FLOAT
       if ((in_flags & EF_ARM_SOFT_FLOAT) != (out_flags & EF_ARM_SOFT_FLOAT))
        {
-         char *s1 = in_flags  & EF_ARM_SOFT_FLOAT ? _("soft") : _("hard");
-         char *s2 = out_flags & EF_ARM_SOFT_FLOAT ? _("soft") : _("hard");
+         /* We can allow interworking between code that is VFP format
+            layout, and uses either soft float or integer regs for
+            passing floating point arguments and results.  We already
+            know that the APCS_FLOAT flags match; similarly for VFP
+            flags.  */
+         if ((in_flags & EF_ARM_APCS_FLOAT) != 0
+             || (in_flags & EF_ARM_VFP_FLOAT) == 0)
+           {
+             if (in_flags & EF_ARM_SOFT_FLOAT)
+               _bfd_error_handler (_("\
+ERROR: %s uses software FP, whereas %s uses hardware FP"),
+                                   bfd_archive_filename (ibfd),
+                                   bfd_get_filename (obfd));
+             else
+               _bfd_error_handler (_("\
+ERROR: %s uses hardware FP, whereas %s uses software FP"),
+                                   bfd_archive_filename (ibfd),
+                                   bfd_get_filename (obfd));
 
-         _bfd_error_handler (_ ("\
-Error: %s uses %s floating point, whereas %s uses %s floating point"),
-                             bfd_archive_filename (ibfd), s1,
-                             bfd_get_filename (obfd), s2);
-         flags_compatible = false;
+             flags_compatible = false;
+           }
        }
 #endif
 
@@ -2274,7 +2371,7 @@ Error: %s uses %s floating point, whereas %s uses %s floating point"),
              _bfd_error_handler (_("\
 Warning: %s supports interworking, whereas %s does not"),
                                  bfd_archive_filename (ibfd),
-                                 bfd_get_filename (obfd));    
+                                 bfd_get_filename (obfd));
            }
          else
            {
@@ -2321,9 +2418,14 @@ elf32_arm_print_private_bfd_data (abfd, ptr)
        fprintf (file, _(" [interworking enabled]"));
 
       if (flags & EF_ARM_APCS_26)
-       fprintf (file, _(" [APCS-26]"));
+       fprintf (file, " [APCS-26]");
       else
-       fprintf (file, _(" [APCS-32]"));
+       fprintf (file, " [APCS-32]");
+
+      if (flags & EF_ARM_VFP_FLOAT)
+       fprintf (file, _(" [VFP float format]"));
+      else
+       fprintf (file, _(" [FPA float format]"));
 
       if (flags & EF_ARM_APCS_FLOAT)
        fprintf (file, _(" [floats passed in float registers]"));
@@ -2340,8 +2442,9 @@ elf32_arm_print_private_bfd_data (abfd, ptr)
       if (flags & EF_ARM_SOFT_FLOAT)
        fprintf (file, _(" [software FP]"));
 
-      flags &= ~(EF_ARM_INTERWORK | EF_ARM_APCS_26 | EF_ARM_APCS_FLOAT | EF_ARM_PIC
-                | EF_ARM_NEW_ABI | EF_ARM_OLD_ABI | EF_ARM_SOFT_FLOAT);
+      flags &= ~(EF_ARM_INTERWORK | EF_ARM_APCS_26 | EF_ARM_APCS_FLOAT
+                | EF_ARM_PIC | EF_ARM_NEW_ABI | EF_ARM_OLD_ABI
+                | EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT);
       break;
 
     case EF_ARM_EABI_VER1:
@@ -2423,8 +2526,8 @@ elf32_arm_get_symbol_type (elf_sym, type)
 }
 
 static asection *
-elf32_arm_gc_mark_hook (abfd, info, rel, h, sym)
-       bfd *abfd;
+elf32_arm_gc_mark_hook (sec, info, rel, h, sym)
+       asection *sec;
        struct bfd_link_info *info ATTRIBUTE_UNUSED;
        Elf_Internal_Rela *rel;
        struct elf_link_hash_entry *h;
@@ -2454,9 +2557,7 @@ elf32_arm_gc_mark_hook (abfd, info, rel, h, sym)
        }
      }
    else
-     {
-       return bfd_section_from_elf_index (abfd, sym->st_shndx);
-     }
+     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
@@ -2870,16 +2971,22 @@ elf32_arm_adjust_dynamic_symbol (info, h)
   if (h->type == STT_FUNC
       || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
     {
+      /* If we link a program (not a DSO), we'll get rid of unnecessary
+        PLT entries; we point to the actual symbols -- even for pic
+        relocs, because a program built with -fpic should have the same
+        result as one built without -fpic, specifically considering weak
+        symbols.
+        FIXME: m68k and i386 differ here, for unclear reasons.  */
       if (! info->shared
-         && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
-         && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0)
+         && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0)
        {
          /* This case can occur if we saw a PLT32 reloc in an input
-             file, but the symbol was never referred to by a dynamic
-             object.  In such a case, we don't actually need to build
-             a procedure linkage table, and we can just do a PC32
-             reloc instead.  */
+            file, but the symbol was not defined by a dynamic object.
+            In such a case, we don't actually need to build a
+            procedure linkage table, and we can just do a PC32 reloc
+            instead.  */
          BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0);
+         h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
          return true;
        }
 
@@ -3121,12 +3228,16 @@ elf32_arm_size_dynamic_sections (output_bfd, info)
          asection ** spp;
 
          for (spp = &s->output_section->owner->sections;
-              *spp != s->output_section;
+              *spp != NULL;
               spp = &(*spp)->next)
-           ;
-         *spp = s->output_section->next;
-         --s->output_section->owner->section_count;
-
+           {
+             if (*spp == s->output_section)
+               {
+                 bfd_section_list_remove (s->output_section->owner, spp);
+                 --s->output_section->owner->section_count;
+                 break;
+               }
+           }
          continue;
        }
 
@@ -3195,6 +3306,9 @@ elf32_arm_discard_copies (h, ignore)
 {
   struct elf32_arm_pcrel_relocs_copied * s;
 
+  if (h->root.root.type == bfd_link_hash_warning)
+    h = (struct elf32_arm_link_hash_entry *) h->root.root.u.i.link;
+
   /* We only discard relocs for symbols defined in a regular object.  */
   if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
     return true;
@@ -3446,6 +3560,31 @@ elf32_arm_finish_dynamic_sections (output_bfd, info)
                }
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
+
+             /* Set the bottom bit of DT_INIT/FINI if the
+                corresponding function is Thumb.  */
+           case DT_INIT:
+             name = info->init_function;
+             goto get_sym;
+           case DT_FINI:
+             name = info->fini_function;
+           get_sym:
+             /* If it wasn't set by elf_bfd_final_link
+                then there is nothing to ajdust.  */
+             if (dyn.d_un.d_val != 0)
+               {
+                 struct elf_link_hash_entry * eh;
+
+                 eh = elf_link_hash_lookup (elf_hash_table (info), name,
+                                            false, false, true);
+                 if (eh != (struct elf_link_hash_entry *) NULL
+                     && ELF_ST_TYPE (eh->type) == STT_ARM_TFUNC)
+                   {
+                     dyn.d_un.d_val |= 1;
+                     bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);                
+                   }
+               }
+             break;
            }
        }
 
@@ -3541,8 +3680,12 @@ elf32_arm_reloc_type_class (rela)
 #define elf_backend_plt_readonly    1
 #define elf_backend_want_got_plt    1
 #define elf_backend_want_plt_sym    0
+#if !USE_REL
+#define elf_backend_rela_normal     1
+#endif
 
 #define elf_backend_got_header_size    12
 #define elf_backend_plt_header_size    PLT_ENTRY_SIZE
 
 #include "elf32-target.h"
+
This page took 0.033994 seconds and 4 git commands to generate.