* config.bfd: Mark arm-*-oabi and thumb-*-oabi as obsolete.
[deliverable/binutils-gdb.git] / bfd / elf32-arm.h
index ac3ec95be3f579309604eb15e53f7ea08755bdf6..e32e871bff47bf0a606d8af44c4f48e8774b0a7a 100644 (file)
@@ -25,9 +25,9 @@
 typedef unsigned long int insn32;
 typedef unsigned short int insn16;
 
-/* In leiu of proper flags, assume all EABIv3 objects are interworkable.  */
+/* In lieu of proper flags, assume all EABIv4 objects are interworkable.  */
 #define INTERWORK_FLAG(abfd)  \
-  (EF_ARM_EABI_VERSION (elf_elfheader (abfd)->e_flags) == EF_ARM_EABI_VER3 \
+  (EF_ARM_EABI_VERSION (elf_elfheader (abfd)->e_flags) == EF_ARM_EABI_VER4 \
   || (elf_elfheader (abfd)->e_flags & EF_ARM_INTERWORK))
 
 /* The linker script knows the section names for placement.
@@ -186,6 +186,9 @@ struct elf32_arm_link_hash_table
        Nonzero if R_ARM_TARGET1 means R_ARM_ABS32.  */
     int target1_is_rel;
 
+    /* The relocation to use for R_ARM_TARGET2 relocations.  */
+    int target2_reloc;
+
     /* The number of bytes in the initial entry in the PLT.  */
     bfd_size_type plt_header_size;
 
@@ -378,6 +381,7 @@ elf32_arm_link_hash_table_create (bfd *abfd)
   ret->no_pipeline_knowledge = 0;
   ret->byteswap_code = 0;
   ret->target1_is_rel = 0;
+  ret->target2_reloc = R_ARM_NONE;
 #ifdef FOUR_WORD_PLT
   ret->plt_header_size = 16;
   ret->plt_entry_size = 16;
@@ -757,8 +761,7 @@ bfd_boolean
 bfd_elf32_arm_process_before_allocation (bfd *abfd,
                                         struct bfd_link_info *link_info,
                                         int no_pipeline_knowledge,
-                                        int byteswap_code,
-                                        int target1_is_rel)
+                                        int byteswap_code)
 {
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *internal_relocs = NULL;
@@ -781,7 +784,7 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd,
   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
 
   globals->no_pipeline_knowledge = no_pipeline_knowledge;
-  globals->target1_is_rel = target1_is_rel;
+
   if (byteswap_code && !bfd_big_endian (abfd))
     {
       _bfd_error_handler (_("%B: BE8 images only valid in big-endian mode."),
@@ -824,6 +827,10 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd,
 
          /* These are the only relocation types we care about.  */
          if (   r_type != R_ARM_PC24
+#ifndef OLD_ARM_ABI
+             && r_type != R_ARM_CALL
+             && r_type != R_ARM_JUMP24
+#endif
              && r_type != R_ARM_THM_PC22)
            continue;
 
@@ -861,6 +868,10 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd,
          switch (r_type)
            {
            case R_ARM_PC24:
+#ifndef OLD_ARM_ABI
+           case R_ARM_CALL:
+           case R_ARM_JUMP24:
+#endif
              /* This one is a call from arm code.  We need to look up
                 the target of the call.  If it is a thumb target, we
                 insert glue.  */
@@ -906,6 +917,34 @@ error_return:
 }
 #endif
 
+
+#ifndef OLD_ARM_ABI
+/* Set target relocation values needed during linking.  */
+
+void
+bfd_elf32_arm_set_target_relocs (struct bfd_link_info *link_info,
+                                int target1_is_rel,
+                                char * target2_type)
+{
+  struct elf32_arm_link_hash_table *globals;
+
+  globals = elf32_arm_hash_table (link_info);
+
+  globals->target1_is_rel = target1_is_rel;
+  if (strcmp (target2_type, "rel") == 0)
+    globals->target2_reloc = R_ARM_REL32;
+  else if (strcmp (target2_type, "abs") == 0)
+    globals->target2_reloc = R_ARM_ABS32;
+  else if (strcmp (target2_type, "got-rel") == 0)
+    globals->target2_reloc = R_ARM_GOT_PREL;
+  else
+    {
+      _bfd_error_handler (_("Invalid TARGET2 relocation type '%s'."),
+                         target2_type);
+    }
+}
+#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
    can occur in any order. So given a thumb form of long branch, and an
@@ -1151,6 +1190,32 @@ elf32_arm_to_thumb_stub (struct bfd_link_info * info,
   return TRUE;
 }
 
+
+#ifndef OLD_ARM_ABI
+/* Some relocations map to different relocations depending on the
+   target.  Return the real relocation.  */
+static int
+arm_real_reloc_type (struct elf32_arm_link_hash_table * globals,
+                    int r_type)
+{
+  switch (r_type)
+    {
+    case R_ARM_TARGET1:
+      if (globals->target1_is_rel)
+       return R_ARM_REL32;
+      else
+       return R_ARM_ABS32;
+
+    case R_ARM_TARGET2:
+      return globals->target2_reloc;
+
+    default:
+      return r_type;
+    }
+}
+#endif /* OLD_ARM_ABI */
+
+
 /* Perform a relocation as part of a final link.  */
 
 static bfd_reloc_status_type
@@ -1186,15 +1251,9 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
 #ifndef OLD_ARM_ABI
   /* Some relocation type map to different relocations depending on the
      target.  We pick the right one here.  */
-  if (r_type == R_ARM_TARGET1)
-    {
-      if (globals->target1_is_rel)
-       r_type = R_ARM_REL32;
-      else
-       r_type = R_ARM_ABS32;
-      
-      howto = &elf32_arm_howto_table[r_type];
-    }
+  r_type = arm_real_reloc_type (globals, r_type);
+  if (r_type != howto->type)
+    howto = elf32_arm_howto_from_type (r_type);
 #endif /* OLD_ARM_ABI */
 
   /* If the start address has been set, then set the EF_ARM_HASENTRY
@@ -1244,7 +1303,10 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
     case R_ARM_ABS32:
     case R_ARM_REL32:
 #ifndef OLD_ARM_ABI
+    case R_ARM_CALL:
+    case R_ARM_JUMP24:
     case R_ARM_XPC25:
+    case R_ARM_PREL31:
 #endif
     case R_ARM_PLT32:
       /* r_symndx will be zero only for relocs against symbols
@@ -1257,7 +1319,11 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
         will use the symbol's value, which may point to a PLT entry, but we
         don't need to handle that here.  If we created a PLT entry, all
         branches in this object should go to it.  */
-      if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32)
+      if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32
+#ifndef OLD_ARM_ABI
+          && r_type != R_ARM_PREL31
+#endif
+          )
          && h != NULL
          && splt != NULL
          && h->plt.offset != (bfd_vma) -1)
@@ -1279,12 +1345,19 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
         into the output file to be resolved at run time.  */
       if (info->shared
          && (input_section->flags & SEC_ALLOC)
-         && (r_type != R_ARM_REL32
-             || !SYMBOL_CALLS_LOCAL (info, h))
+         && ((r_type != R_ARM_REL32
+#ifndef OLD_ARM_ABI
+             && r_type != R_ARM_PREL31
+#endif
+             ) || !SYMBOL_CALLS_LOCAL (info, h))
          && (h == NULL
              || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
              || h->root.type != bfd_link_hash_undefweak)
          && r_type != R_ARM_PC24
+#ifndef OLD_ARM_ABI
+         && r_type != R_ARM_CALL
+         && r_type != R_ARM_JUMP24
+#endif
          && r_type != R_ARM_PLT32)
        {
          Elf_Internal_Rela outrel;
@@ -1330,8 +1403,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                   && h->dynindx != -1
                   && (!info->shared
                       || !info->symbolic
-                      || (h->elf_link_hash_flags
-                          & ELF_LINK_HASH_DEF_REGULAR) == 0))
+                      || !h->def_regular))
            outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
          else
            {
@@ -1358,6 +1430,8 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
        {
 #ifndef OLD_ARM_ABI
        case R_ARM_XPC25:         /* Arm BLX instruction.  */
+       case R_ARM_CALL:
+       case R_ARM_JUMP24:
 #endif
        case R_ARM_PC24:          /* Arm B/BL instruction */
        case R_ARM_PLT32:
@@ -1481,6 +1555,24 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                    + input_section->output_offset + rel->r_offset);
          value += addend;
          break;
+
+#ifndef OLD_ARM_ABI
+       case R_ARM_PREL31:
+         value -= (input_section->output_section->vma
+                   + input_section->output_offset + rel->r_offset);
+         value += signed_addend;
+         if (! h || h->root.type != bfd_link_hash_undefweak)
+           {
+             /* Check for overflow */
+             if ((value ^ (value >> 1)) & (1 << 30))
+               return bfd_reloc_overflow;
+           }
+         value &= 0x7fffffff;
+         value |= (bfd_get_32 (input_bfd, hit_data) & 0x80000000);
+         if (sym_flags == STT_ARM_TFUNC)
+           value |= 1;
+         break;
+#endif
        }
 
       bfd_put_32 (input_bfd, value, hit_data);
@@ -1770,6 +1862,9 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                                       (bfd_vma) 0);
 
     case R_ARM_GOT32:
+#ifndef OLD_ARM_ABI
+    case R_ARM_GOT_PREL:
+#endif
       /* Relocation is to the entry for this symbol in the
          global offset table.  */
       if (sgot == NULL)
@@ -1858,6 +1953,8 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
 
          value = sgot->output_offset + off;
        }
+      if (r_type != R_ARM_GOT32)
+       value += sgot->output_section->vma;
 
       return _bfd_final_link_relocate (howto, input_bfd, input_section,
                                       contents, rel->r_offset, value,
@@ -1947,6 +2044,10 @@ arm_add_to_rel (bfd *              abfd,
          break;
 
        case R_ARM_PC24:
+#ifndef OLD_ARM_ABI
+       case R_ARM_CALL:
+       case R_ARM_JUMP24:
+#endif
          addend <<= howto->size;
          addend += increment;
 
@@ -2107,15 +2208,17 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
              switch (r_type)
                {
                case R_ARM_PC24:
+#ifndef OLD_ARM_ABI
+               case R_ARM_CALL:
+               case R_ARM_JUMP24:
+#endif
                case R_ARM_ABS32:
                case R_ARM_THM_PC22:
                case R_ARM_PLT32:
 
                  if (info->shared
-                     && (
-                         (!info->symbolic && h->dynindx != -1)
-                         || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
-                         )
+                     && ((!info->symbolic && h->dynindx != -1)
+                         || !h->def_regular)
                      && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                      && ((input_section->flags & SEC_ALLOC) != 0
                          /* DWARF will emit R_ARM_ABS32 relocations in its
@@ -2123,8 +2226,7 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
                             in shared libraries.  We can't do anything
                             with them here.  */
                          || ((input_section->flags & SEC_DEBUGGING) != 0
-                             && (h->elf_link_hash_flags
-                                 & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
+                             && h->def_dynamic))
                      )
                    relocation = 0;
                  break;
@@ -2134,13 +2236,15 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
                  break;
 
                case R_ARM_GOT32:
+#ifndef OLD_ARM_ABI
+               case R_ARM_GOT_PREL:
+#endif
                  if ((WILL_CALL_FINISH_DYNAMIC_SYMBOL
                       (elf_hash_table (info)->dynamic_sections_created,
                        info->shared, h))
                      && (!info->shared
                          || (!info->symbolic && h->dynindx != -1)
-                         || (h->elf_link_hash_flags
-                             & ELF_LINK_HASH_DEF_REGULAR) == 0))
+                         || !h->def_regular))
                    relocation = 0;
                  break;
 
@@ -2185,8 +2289,9 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
              if ((! h ||
                   h->root.type != bfd_link_hash_undefined)
                  && (!((*info->callbacks->reloc_overflow)
-                       (info, name, howto->name, (bfd_vma) 0,
-                        input_bfd, input_section, rel->r_offset))))
+                       (info, (h ? &h->root : NULL), name, howto->name,
+                        (bfd_vma) 0, input_bfd, input_section,
+                        rel->r_offset))))
                  return FALSE;
              break;
 
@@ -2248,6 +2353,7 @@ elf32_arm_object_p (bfd *abfd)
 }
 
 /* Function to keep ARM specific flags in the ELF header.  */
+
 static bfd_boolean
 elf32_arm_set_private_flags (bfd *abfd, flagword flags)
 {
@@ -2423,7 +2529,7 @@ elf32_arm_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
   if (EF_ARM_EABI_VERSION (in_flags) != EF_ARM_EABI_VERSION (out_flags))
     {
       _bfd_error_handler
-       (_("ERROR: %B is compiled for EABI version %d, whereas %B is compiled for version %d"),
+       (_("ERROR: Source object %B has EABI version %d, but target %B has EABI version %d"),
         ibfd, obfd,
         (in_flags & EF_ARM_EABIMASK) >> 24,
         (out_flags & EF_ARM_EABIMASK) >> 24);
@@ -2624,6 +2730,10 @@ elf32_arm_print_private_bfd_data (bfd *abfd, void * ptr)
 
     case EF_ARM_EABI_VER3:
       fprintf (file, _(" [Version3 EABI]"));
+      break;
+
+    case EF_ARM_EABI_VER4:
+      fprintf (file, _(" [Version4 EABI]"));
 
       if (flags & EF_ARM_BE8)
        fprintf (file, _(" [BE8]"));
@@ -2731,6 +2841,9 @@ elf32_arm_gc_sweep_hook (bfd *                     abfd ATTRIBUTE_UNUSED,
   const Elf_Internal_Rela *rel, *relend;
   unsigned long r_symndx;
   struct elf_link_hash_entry *h;
+  struct elf32_arm_link_hash_table * globals;
+
+  globals = elf32_arm_hash_table (info);
 
   elf_section_data (sec)->local_dynrel = NULL;
 
@@ -2740,62 +2853,79 @@ elf32_arm_gc_sweep_hook (bfd *                     abfd ATTRIBUTE_UNUSED,
 
   relend = relocs + sec->reloc_count;
   for (rel = relocs; rel < relend; rel++)
-    switch (ELF32_R_TYPE (rel->r_info))
-      {
-      case R_ARM_GOT32:
-       r_symndx = ELF32_R_SYM (rel->r_info);
-       if (r_symndx >= symtab_hdr->sh_info)
-         {
-           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-           if (h->got.refcount > 0)
-             h->got.refcount -= 1;
-         }
-       else if (local_got_refcounts != NULL)
-         {
-           if (local_got_refcounts[r_symndx] > 0)
-             local_got_refcounts[r_symndx] -= 1;
-         }
-       break;
-
-      case R_ARM_ABS32:
-      case R_ARM_REL32:
-      case R_ARM_TARGET1:
-      case R_ARM_PC24:
-      case R_ARM_PLT32:
-       r_symndx = ELF32_R_SYM (rel->r_info);
-       if (r_symndx >= symtab_hdr->sh_info)
-         {
-           struct elf32_arm_link_hash_entry *eh;
-           struct elf32_arm_relocs_copied **pp;
-           struct elf32_arm_relocs_copied *p;
+    {
+      int r_type;
 
-           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+      r_type = ELF32_R_TYPE (rel->r_info);
+#ifndef OLD_ARM_ABI
+      r_type = arm_real_reloc_type (globals, r_type);
+#endif
+      switch (r_type)
+       {
+       case R_ARM_GOT32:
+#ifndef OLD_ARM_ABI
+       case R_ARM_GOT_PREL:
+#endif
+         r_symndx = ELF32_R_SYM (rel->r_info);
+         if (r_symndx >= symtab_hdr->sh_info)
+           {
+             h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+             if (h->got.refcount > 0)
+               h->got.refcount -= 1;
+           }
+         else if (local_got_refcounts != NULL)
+           {
+             if (local_got_refcounts[r_symndx] > 0)
+               local_got_refcounts[r_symndx] -= 1;
+           }
+         break;
 
-           if (h->plt.refcount > 0)
-             h->plt.refcount -= 1;
+       case R_ARM_ABS32:
+       case R_ARM_REL32:
+       case R_ARM_PC24:
+       case R_ARM_PLT32:
+#ifndef OLD_ARM_ABI
+       case R_ARM_CALL:
+       case R_ARM_JUMP24:
+       case R_ARM_PREL31:
+#endif
+         r_symndx = ELF32_R_SYM (rel->r_info);
+         if (r_symndx >= symtab_hdr->sh_info)
+           {
+             struct elf32_arm_link_hash_entry *eh;
+             struct elf32_arm_relocs_copied **pp;
+             struct elf32_arm_relocs_copied *p;
 
-           if (ELF32_R_TYPE (rel->r_info) == R_ARM_ABS32
-               || ELF32_R_TYPE (rel->r_info) == R_ARM_REL32
-               || ELF32_R_TYPE (rel->r_info) == R_ARM_TARGET1)
-             {
-               eh = (struct elf32_arm_link_hash_entry *) h;
+             h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 
-               for (pp = &eh->relocs_copied; (p = *pp) != NULL;
-                    pp = &p->next)
-               if (p->section == sec)
-                 {
-                   p->count -= 1;
-                   if (p->count == 0)
-                     *pp = p->next;
-                   break;
-                 }
-             }
-         }
-       break;
+             if (h->plt.refcount > 0)
+               h->plt.refcount -= 1;
 
-      default:
-       break;
-      }
+             if (r_type == R_ARM_ABS32
+#ifndef OLD_ARM_ABI
+                 || r_type == R_ARM_PREL31
+#endif
+                 || r_type == R_ARM_REL32)
+               {
+                 eh = (struct elf32_arm_link_hash_entry *) h;
+
+                 for (pp = &eh->relocs_copied; (p = *pp) != NULL;
+                      pp = &p->next)
+                 if (p->section == sec)
+                   {
+                     p->count -= 1;
+                     if (p->count == 0)
+                       *pp = p->next;
+                     break;
+                   }
+               }
+           }
+         break;
+
+       default:
+         break;
+       }
+    }
 
   return TRUE;
 }
@@ -2838,16 +2968,24 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
     {
       struct elf_link_hash_entry *h;
       unsigned long r_symndx;
+      int r_type;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
+      r_type = ELF32_R_TYPE (rel->r_info);
+#ifndef OLD_ARM_ABI
+      r_type = arm_real_reloc_type (htab, r_type);
+#endif
       if (r_symndx < symtab_hdr->sh_info)
         h = NULL;
       else
         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 
-      switch (ELF32_R_TYPE (rel->r_info))
+      switch (r_type)
         {
          case R_ARM_GOT32:
+#ifndef OLD_ARM_ABI
+         case R_ARM_GOT_PREL:
+#endif
            /* This symbol requires a global offset table entry.  */
            if (h != NULL)
              {
@@ -2872,7 +3010,9 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
                  }
                local_got_refcounts[r_symndx] += 1;
              }
-           break;
+           if (r_type == R_ARM_GOT32)
+             break;
+           /* Fall through.  */
 
          case R_ARM_GOTOFF:
          case R_ARM_GOTPC:
@@ -2887,9 +3027,13 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
          case R_ARM_ABS32:
          case R_ARM_REL32:
-         case R_ARM_TARGET1:
          case R_ARM_PC24:
          case R_ARM_PLT32:
+#ifndef OLD_ARM_ABI
+         case R_ARM_CALL:
+         case R_ARM_JUMP24:
+         case R_ARM_PREL31:
+#endif
            if (h != NULL)
              {
                /* If this reloc is in a read-only section, we might
@@ -2899,15 +3043,19 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
                   Tentatively set the flag for now, and correct in
                   adjust_dynamic_symbol.  */
                if (!info->shared)
-                 h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
+                 h->non_got_ref = 1;
 
                /* We may need a .plt entry if the function this reloc
                   refers to is in a different object.  We can't tell for
                   sure yet, because something later might force the
                   symbol local.  */
-               if (ELF32_R_TYPE (rel->r_info) == R_ARM_PC24
-                   || ELF32_R_TYPE (rel->r_info) == R_ARM_PLT32)
-                 h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+               if (r_type == R_ARM_PC24
+#ifndef OLD_ARM_ABI
+                   || r_type == R_ARM_CALL
+                   || r_type == R_ARM_JUMP24
+#endif
+                   || r_type == R_ARM_PLT32)
+                 h->needs_plt = 1;
 
                /* If we create a PLT entry, this relocation will reference
                   it, even if it's an ABS32 relocation.  */
@@ -2928,14 +3076,17 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
                relocs_copied field of the hash table entry.  */
            if (info->shared
                && (sec->flags & SEC_ALLOC) != 0
-               && ((ELF32_R_TYPE (rel->r_info) != R_ARM_PC24
-                    && ELF32_R_TYPE (rel->r_info) != R_ARM_PLT32
-                    && ELF32_R_TYPE (rel->r_info) != R_ARM_REL32
-                    && ELF32_R_TYPE (rel->r_info) != R_ARM_TARGET1)
+               && ((r_type != R_ARM_PC24
+                    && r_type != R_ARM_PLT32
+#ifndef OLD_ARM_ABI
+                    && r_type != R_ARM_CALL
+                    && r_type != R_ARM_JUMP24
+                    && r_type != R_ARM_PREL31
+#endif
+                    && r_type != R_ARM_REL32)
                    || (h != NULL
                        && (! info->symbolic
-                           || (h->elf_link_hash_flags
-                               & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+                           || !h->def_regular))))
              {
                struct elf32_arm_relocs_copied *p, **head;
 
@@ -3015,9 +3166,11 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
                    p->count = 0;
                  }
 
-               if (ELF32_R_TYPE (rel->r_info) == R_ARM_ABS32
-                   || ELF32_R_TYPE (rel->r_info) == R_ARM_REL32
-                   || ELF32_R_TYPE (rel->r_info) == R_ARM_TARGET1)
+               if (r_type == R_ARM_ABS32
+#ifndef OLD_ARM_ABI
+                   || r_type == R_ARM_PREL31
+#endif
+                   || r_type == R_ARM_REL32)
                  p->count += 1;
              }
            break;
@@ -3050,6 +3203,14 @@ is_arm_mapping_symbol_name (const char * name)
     && (name[2] == 0);
 }
 
+/* Treat mapping symbols as special target symbols.  */
+
+static bfd_boolean
+elf32_arm_is_target_special_symbol (bfd * abfd ATTRIBUTE_UNUSED, asymbol * sym)
+{
+  return is_arm_mapping_symbol_name (sym->name);
+}
+
 /* This is a copy of elf_find_function() from elf.c except that
    ARM mapping symbols are ignored when looking for function names
    and STT_ARM_TFUNC is considered to a function type.  */
@@ -3073,9 +3234,6 @@ arm_elf_find_function (bfd *         abfd ATTRIBUTE_UNUSED,
 
       q = (elf_symbol_type *) *p;
 
-      if (bfd_get_section (&q->symbol) != section)
-       continue;
-
       switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
        {
        default:
@@ -3091,7 +3249,7 @@ arm_elf_find_function (bfd *         abfd ATTRIBUTE_UNUSED,
            continue;
          /* Fall through.  */
        case STT_NOTYPE:
-         if (q->symbol.section == section
+         if (bfd_get_section (&q->symbol) == section
              && q->symbol.value >= low_func
              && q->symbol.value <= offset)
            {
@@ -3182,20 +3340,17 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info,
 
   /* Make sure we know what is going on here.  */
   BFD_ASSERT (dynobj != NULL
-             && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
-                 || h->weakdef != NULL
-                 || ((h->elf_link_hash_flags
-                      & ELF_LINK_HASH_DEF_DYNAMIC) != 0
-                     && (h->elf_link_hash_flags
-                         & ELF_LINK_HASH_REF_REGULAR) != 0
-                     && (h->elf_link_hash_flags
-                         & ELF_LINK_HASH_DEF_REGULAR) == 0)));
+             && (h->needs_plt
+                 || h->u.weakdef != NULL
+                 || (h->def_dynamic
+                     && h->ref_regular
+                     && !h->def_regular)));
 
   /* If this is a function, put it in the procedure linkage table.  We
      will fill in the contents of the procedure linkage table later,
      when we know the address of the .got section.  */
   if (h->type == STT_FUNC
-      || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+      || h->needs_plt)
     {
       if (h->plt.refcount <= 0
          || SYMBOL_CALLS_LOCAL (info, h)
@@ -3208,28 +3363,28 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info,
             such a case, we don't actually need to build a procedure
             linkage table, and we can just do a PC24 reloc instead.  */
          h->plt.offset = (bfd_vma) -1;
-         h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+         h->needs_plt = 0;
        }
 
       return TRUE;
     }
   else
     /* It's possible that we incorrectly decided a .plt reloc was
-       needed for an R_ARM_PC24 reloc to a non-function sym in
-       check_relocs.  We can't decide accurately between function and
-       non-function syms in check-relocs;  Objects loaded later in
+       needed for an R_ARM_PC24 or similar reloc to a non-function sym
+       in check_relocs.  We can't decide accurately between function
+       and non-function syms in check-relocs; Objects loaded later in
        the link may change h->type.  So fix it now.  */
     h->plt.offset = (bfd_vma) -1;
 
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.  */
-  if (h->weakdef != NULL)
+  if (h->u.weakdef != NULL)
     {
-      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
-                 || h->weakdef->root.type == bfd_link_hash_defweak);
-      h->root.u.def.section = h->weakdef->root.u.def.section;
-      h->root.u.def.value = h->weakdef->root.u.def.value;
+      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+                 || h->u.weakdef->root.type == bfd_link_hash_defweak);
+      h->root.u.def.section = h->u.weakdef->root.u.def.section;
+      h->root.u.def.value = h->u.weakdef->root.u.def.value;
       return TRUE;
     }
 
@@ -3266,7 +3421,7 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info,
       srel = bfd_get_section_by_name (dynobj, ".rel.bss");
       BFD_ASSERT (srel != NULL);
       srel->size += sizeof (Elf32_External_Rel);
-      h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
+      h->needs_copy = 1;
     }
 
   /* We need to figure out the alignment required for this symbol.  I
@@ -3322,7 +3477,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
       /* Make sure this symbol is output as a dynamic symbol.
         Undefined weak syms won't yet be marked as dynamic.  */
       if (h->dynindx == -1
-         && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+         && !h->forced_local)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
            return FALSE;
@@ -3346,7 +3501,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
             pointers compare as equal between the normal executable and
             the shared library.  */
          if (! info->shared
-             && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+             && !h->def_regular)
            {
              h->root.u.def.section = s;
              h->root.u.def.value = h->plt.offset;
@@ -3366,13 +3521,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
       else
        {
          h->plt.offset = (bfd_vma) -1;
-         h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+         h->needs_plt = 0;
        }
     }
   else
     {
       h->plt.offset = (bfd_vma) -1;
-      h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+      h->needs_plt = 0;
     }
 
   if (h->got.refcount > 0)
@@ -3383,7 +3538,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
       /* Make sure this symbol is output as a dynamic symbol.
         Undefined weak syms won't yet be marked as dynamic.  */
       if (h->dynindx == -1
-         && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+         && !h->forced_local)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
            return FALSE;
@@ -3429,9 +3584,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
         symbols which turn out to need copy relocs or are not
         dynamic.  */
 
-      if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
-         && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
-              && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+      if (!h->non_got_ref
+         && ((h->def_dynamic
+              && !h->def_regular)
              || (htab->root.dynamic_sections_created
                  && (h->root.type == bfd_link_hash_undefweak
                      || h->root.type == bfd_link_hash_undefined))))
@@ -3439,7 +3594,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
          /* Make sure this symbol is output as a dynamic symbol.
             Undefined weak syms won't yet be marked as dynamic.  */
          if (h->dynindx == -1
-             && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+             && !h->forced_local)
            {
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
                return FALSE;
@@ -3733,7 +3888,8 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, struct bfd_link_info * info,
                        splt->contents + h->plt.offset + 4 * i);
          
          /* Fill in the entry in the .rel.plt section.  */
-         rel.r_offset = (splt->output_offset
+         rel.r_offset = (splt->output_section->vma
+                         + splt->output_offset
                          + h->plt.offset + 4 * (i - 1));
          rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_GLOB_DAT);
        }
@@ -3790,7 +3946,7 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, struct bfd_link_info * info,
       loc = srel->contents + plt_index * sizeof (Elf32_External_Rel);
       bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
 
-      if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+      if (!h->def_regular)
        {
          /* Mark the symbol as undefined, rather than as defined in
             the .plt section.  Leave the value alone.  */
@@ -3799,8 +3955,7 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, struct bfd_link_info * info,
             Otherwise, the PLT entry would provide a definition for
             the symbol even if the symbol wasn't defined anywhere,
             and so the symbol would never be NULL.  */
-         if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK)
-             == 0)
+         if (!h->ref_regular_nonweak)
            sym->st_value = 0;
        }
     }
@@ -3844,7 +3999,7 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, struct bfd_link_info * info,
       bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
     }
 
-  if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
+  if (h->needs_copy)
     {
       asection * s;
       Elf_Internal_Rela rel;
@@ -3927,7 +4082,16 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
            case DT_SYMTAB:
              name = ".dynsym";
              goto get_vma_if_bpabi;
-             
+           case DT_VERSYM:
+             name = ".gnu.version";
+             goto get_vma_if_bpabi;
+           case DT_VERDEF:
+             name = ".gnu.version_d";
+             goto get_vma_if_bpabi;
+           case DT_VERNEED:
+             name = ".gnu.version_r";
+             goto get_vma_if_bpabi;
+
            case DT_PLTGOT:
              name = ".got";
              goto get_vma;
@@ -4126,9 +4290,6 @@ elf32_arm_reloc_type_class (const Elf_Internal_Rela *rela)
     }
 }
 
-static bfd_boolean elf32_arm_section_flags           (flagword *, const Elf_Internal_Shdr *);
-static void        elf32_arm_final_write_processing  (bfd *, bfd_boolean);
-
 /* Set the right machine number for an Arm ELF file.  */
 
 static bfd_boolean
@@ -4146,6 +4307,65 @@ elf32_arm_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED
   bfd_arm_update_notes (abfd, ARM_NOTE_SECTION);
 }
 
+/* Return TRUE if this is an unwinding table entry.  */
+
+static bfd_boolean
+is_arm_elf_unwind_section_name (bfd * abfd ATTRIBUTE_UNUSED, const char * name)
+{
+  size_t len1, len2;
+
+  len1 = sizeof (ELF_STRING_ARM_unwind) - 1;
+  len2 = sizeof (ELF_STRING_ARM_unwind_once) - 1;
+  return (strncmp (name, ELF_STRING_ARM_unwind, len1) == 0
+         || strncmp (name, ELF_STRING_ARM_unwind_once, len2) == 0);
+}
+
+
+/* Set the type and flags for an ARM section.  We do this by
+   the section name, which is a hack, but ought to work.  */
+
+static bfd_boolean
+elf32_arm_fake_sections (bfd * abfd, Elf_Internal_Shdr * hdr, asection * sec)
+{
+  const char * name;
+
+  name = bfd_get_section_name (abfd, sec);
+
+  if (is_arm_elf_unwind_section_name (abfd, name))
+    {
+      hdr->sh_type = SHT_ARM_EXIDX;
+      hdr->sh_flags |= SHF_LINK_ORDER;
+    }
+  return TRUE;
+}
+
+/* Handle an ARM specific section when reading an object file.
+   This is called when elf.c finds a section with an unknown type.  */
+
+static bfd_boolean
+elf32_arm_section_from_shdr (bfd *abfd,
+                            Elf_Internal_Shdr * hdr,
+                            const char *name)
+{
+  /* There ought to be a place to keep ELF backend specific flags, but
+     at the moment there isn't one.  We just keep track of the
+     sections by their name, instead.  Fortunately, the ABI gives
+     names for all the ARM specific sections, so we will probably get
+     away with this.  */
+  switch (hdr->sh_type)
+    {
+    case SHT_ARM_EXIDX:
+      break;
+
+    default:
+      return FALSE;
+    }
+
+  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+    return FALSE;
+
+  return TRUE;
+}
 
 /* Called for each symbol.  Builds a section map based on mapping symbols.
    Does not alter any of the symbols.  */
@@ -4300,6 +4520,7 @@ elf32_arm_write_section (bfd *output_bfd ATTRIBUTE_UNUSED, asection *sec,
 #define bfd_elf32_bfd_reloc_type_lookup                elf32_arm_reloc_type_lookup
 #define bfd_elf32_find_nearest_line            elf32_arm_find_nearest_line
 #define bfd_elf32_new_section_hook             elf32_arm_new_section_hook
+#define bfd_elf32_bfd_is_target_special_symbol elf32_arm_is_target_special_symbol
 
 #define elf_backend_get_symbol_type             elf32_arm_get_symbol_type
 #define elf_backend_gc_mark_hook                elf32_arm_gc_mark_hook
@@ -4317,6 +4538,8 @@ elf32_arm_write_section (bfd *output_bfd ATTRIBUTE_UNUSED, asection *sec,
 #define elf_backend_reloc_type_class           elf32_arm_reloc_type_class
 #define elf_backend_object_p                   elf32_arm_object_p
 #define elf_backend_section_flags              elf32_arm_section_flags
+#define elf_backend_fake_sections              elf32_arm_fake_sections
+#define elf_backend_section_from_shdr                  elf32_arm_section_from_shdr
 #define elf_backend_final_write_processing      elf32_arm_final_write_processing
 #define elf_backend_copy_indirect_symbol        elf32_arm_copy_indirect_symbol
 
This page took 0.034291 seconds and 4 git commands to generate.