2011-06-22 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
[deliverable/binutils-gdb.git] / bfd / elf32-arm.c
index 671a20996ee2ef2287be0dcbf43859a3fd229676..257f7a5e6eeda14e634bdc89369218a0f70518a2 100644 (file)
@@ -229,8 +229,8 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
         bfd_elf_generic_reloc, /* special_function */
         "R_ARM_THM_CALL",      /* name */
         FALSE,                 /* partial_inplace */
-        0x07ff07ff,            /* src_mask */
-        0x07ff07ff,            /* dst_mask */
+        0x07ff2fff,            /* src_mask */
+        0x07ff2fff,            /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
   HOWTO (R_ARM_THM_PC8,                /* type */
@@ -293,7 +293,7 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
   HOWTO (R_ARM_XPC25,          /* type */
         2,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        25,                    /* bitsize */
+        24,                    /* bitsize */
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed,/* complain_on_overflow */
@@ -308,15 +308,15 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
   HOWTO (R_ARM_THM_XPC22,      /* type */
         2,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        22,                    /* bitsize */
+        24,                    /* bitsize */
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_ARM_THM_XPC22",     /* name */
         FALSE,                 /* partial_inplace */
-        0x07ff07ff,            /* src_mask */
-        0x07ff07ff,            /* dst_mask */
+        0x07ff2fff,            /* src_mask */
+        0x07ff2fff,            /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
   /* Dynamic TLS relocations.  */
@@ -3427,6 +3427,7 @@ arm_stub_is_thumb (enum elf32_arm_stub_type stub_type)
     case arm_stub_long_branch_v4t_thumb_arm:
     case arm_stub_short_branch_v4t_thumb_arm:
     case arm_stub_long_branch_v4t_thumb_arm_pic:
+    case arm_stub_long_branch_v4t_thumb_tls_pic:
     case arm_stub_long_branch_thumb_only_pic:
       return TRUE;
     case arm_stub_none:
@@ -8303,7 +8304,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                     case, mode switching is performed by the stub.  */
                  if (branch_type == ST_BRANCH_TO_THUMB && !stub_entry)
                    value |= (1 << 28);
-                 else
+                 else if (stub_entry || branch_type != ST_BRANCH_UNKNOWN)
                    {
                      value &= ~(bfd_vma)(1 << 28);
                      value |= (1 << 24);
@@ -9304,6 +9305,9 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
            || ELF32_R_TYPE(rel->r_info) == R_ARM_THM_TLS_CALL)
          {
            bfd_signed_vma offset;
+           /* TLS stubs are arm mode.  The original symbol is a
+              data object, so branch_type is bogus.  */
+           branch_type = ST_BRANCH_TO_ARM;
            enum elf32_arm_stub_type stub_type
              = arm_type_of_stub (info, input_section, rel,
                                  st_type, &branch_type,
@@ -9348,16 +9352,25 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                           input_section->output_offset
                           + rel->r_offset + 4);
            
-               /* Round up the offset to a word boundary */
-               offset = (offset + 2) & ~2;
+               if (stub_type != arm_stub_none
+                   && arm_stub_is_thumb (stub_type))
+                 {
+                   lower_insn = 0xd000;
+                 }
+               else
+                 {
+                   lower_insn = 0xc000;
+                   /* Round up the offset to a word boundary */
+                   offset = (offset + 2) & ~2;
+                 }
+
                neg = offset < 0;
                upper_insn = (0xf000
                              | ((offset >> 12) & 0x3ff)
                              | (neg << 10));
-               lower_insn = (0xc000
-                             | (((!((offset >> 23) & 1)) ^ neg) << 13)
+               lower_insn |= (((!((offset >> 23) & 1)) ^ neg) << 13)
                              | (((!((offset >> 22) & 1)) ^ neg) << 11)
-                             | ((offset >> 1) & 0x7ff));
+                             | ((offset >> 1) & 0x7ff);
                bfd_put_16 (input_bfd, upper_insn, hit_data);
                bfd_put_16 (input_bfd, lower_insn, hit_data + 2);
                return bfd_reloc_ok;
@@ -9441,7 +9454,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
       }
 
     case R_ARM_TLS_LE32:
-      if (info->shared)
+      if (info->shared && !info->pie)
        {
          (*_bfd_error_handler)
            (_("%B(%A+0x%lx): R_ARM_TLS_LE32 relocation not permitted in shared object"),
@@ -10220,7 +10233,7 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
                    - relocation;
                  addend += msec->output_section->vma + msec->output_offset;
 
-                 /* Cases here must match those in the preceeding
+                 /* Cases here must match those in the preceding
                     switch statement.  */
                  switch (r_type)
                    {
@@ -12454,6 +12467,8 @@ elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info,
   Elf_Internal_Shdr **elf_shdrp;
   bfd_boolean again;
 
+  _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
+
   /* Marking EH data may cause additional code sections to be marked,
      requiring multiple passes.  */
   again = TRUE;
@@ -12774,12 +12789,6 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    /* When warning symbols are created, they **replace** the "real"
-       entry in the hash table, thus we never get to see the real
-       symbol in a hash traversal.  So look at it now.  */
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   eh = (struct elf32_arm_link_hash_entry *) h;
 
   info = (struct bfd_link_info *) inf;
@@ -13143,9 +13152,6 @@ elf32_arm_readonly_dynrelocs (struct elf_link_hash_entry * h, void * inf)
   struct elf32_arm_link_hash_entry * eh;
   struct elf_dyn_relocs * p;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   eh = (struct elf32_arm_link_hash_entry *) h;
   for (p = eh->dyn_relocs; p != NULL; p = p->next)
     {
@@ -13731,6 +13737,10 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
   dynobj = elf_hash_table (info)->dynobj;
 
   sgot = htab->root.sgotplt;
+  /* A broken linker script might have discarded the dynamic sections.
+     Catch this here so that we do not seg-fault later on.  */
+  if (sgot != NULL && bfd_is_abs_section (sgot->output_section))
+    return FALSE;
   sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
 
   if (elf_hash_table (info)->dynamic_sections_created)
@@ -15118,12 +15128,16 @@ elf32_arm_swap_symbol_in (bfd * abfd,
 
   /* New EABI objects mark thumb function symbols by setting the low bit of
      the address.  */
-  if ((ELF_ST_TYPE (dst->st_info) == STT_FUNC
-       || ELF_ST_TYPE (dst->st_info) == STT_GNU_IFUNC)
-      && (dst->st_value & 1))
+  if (ELF_ST_TYPE (dst->st_info) == STT_FUNC
+      || ELF_ST_TYPE (dst->st_info) == STT_GNU_IFUNC)
     {
-      dst->st_value &= ~(bfd_vma) 1;
-      dst->st_target_internal = ST_BRANCH_TO_THUMB;
+      if (dst->st_value & 1)
+       {
+         dst->st_value &= ~(bfd_vma) 1;
+         dst->st_target_internal = ST_BRANCH_TO_THUMB;
+       }
+      else
+       dst->st_target_internal = ST_BRANCH_TO_ARM;
     }
   else if (ELF_ST_TYPE (dst->st_info) == STT_ARM_TFUNC)
     {
@@ -15133,7 +15147,7 @@ elf32_arm_swap_symbol_in (bfd * abfd,
   else if (ELF_ST_TYPE (dst->st_info) == STT_SECTION)
     dst->st_target_internal = ST_BRANCH_LONG;
   else
-    dst->st_target_internal = ST_BRANCH_TO_ARM;
+    dst->st_target_internal = ST_BRANCH_UNKNOWN;
 
   return TRUE;
 }
@@ -15431,7 +15445,7 @@ elf32_arm_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
   bfd_boolean flags_compatible = TRUE;
   asection *sec;
 
-  /* Check if we have the same endianess.  */
+  /* Check if we have the same endianness.  */
   if (! _bfd_generic_verify_endian_match (ibfd, obfd))
     return FALSE;
 
This page took 0.034675 seconds and 4 git commands to generate.