ops - omited from previous delta
[binutils-gdb.git] / bfd / elf64-sparc.c
index ca2e7c1d2f4f5355bb15d88dd7c68383fcf68406..e63bc3bd3edd6e5ea1b17320d50027b68822b455 100644 (file)
@@ -1557,12 +1557,6 @@ sparc64_elf_adjust_dynamic_symbol (info, h)
       s = bfd_get_section_by_name (dynobj, ".rela.plt");
       BFD_ASSERT (s != NULL);
 
-      /* The first plt entries are reserved, and the relocations must
-        pair up exactly.  */
-      if (s->_raw_size == 0)
-       s->_raw_size += (PLT_HEADER_SIZE/PLT_ENTRY_SIZE
-                        * sizeof (Elf64_External_Rela));
-
       s->_raw_size += sizeof (Elf64_External_Rela);
 
       /* The procedure linkage table size is bounded by the magnitude
@@ -1803,6 +1797,7 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
        {
          if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))
            return false;
+         info->flags |= DF_TEXTREL;
        }
 
       /* Add dynamic STT_REGISTER symbols and corresponding DT_SPARC_REGISTER
@@ -2078,7 +2073,15 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                      (!info->shared || info->no_undefined
                       || ELF_ST_VISIBILITY (h->other)))))
                return false;
-             relocation = 0;
+
+             /* To avoid generating warning messages about truncated
+                relocations, set the relocation's address to be the same as
+                the start of this section.  */
+
+             if (input_section->output_section != NULL)
+               relocation = input_section->output_section->vma;
+             else
+               relocation = 0;
            }
        }
 
@@ -2355,7 +2358,6 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                off &= ~1;
              else
                {
-                 bfd_put_64 (output_bfd, relocation, sgot->contents + off);
                  local_got_offsets[r_symndx] |= 1;
 
                  if (info->shared)
@@ -2363,6 +2365,13 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                      asection *srelgot;
                      Elf_Internal_Rela outrel;
 
+                     /* The Solaris 2.7 64-bit linker adds the contents
+                        of the location to the value of the reloc.
+                        Note this is different behaviour to the
+                        32-bit linker, which both adds the contents
+                        and ignores the addend.  So clear the location.  */
+                     bfd_put_64 (output_bfd, 0, sgot->contents + off);
+                     
                      /* We need to generate a R_SPARC_RELATIVE reloc
                         for the dynamic linker.  */
                      srelgot = bfd_get_section_by_name(dynobj, ".rela.got");
@@ -2379,6 +2388,8 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                                                  + srelgot->reloc_count));
                      ++srelgot->reloc_count;
                    }
+                 else
+                   bfd_put_64 (output_bfd, relocation, sgot->contents + off);
                }
              relocation = sgot->output_offset + off - got_base;
            }
@@ -2685,9 +2696,14 @@ sparc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
       rela.r_offset += (splt->output_section->vma + splt->output_offset);
       rela.r_info = ELF64_R_INFO (h->dynindx, R_SPARC_JMP_SLOT);
 
+      /* Adjust for the first 4 reserved elements in the .plt section
+        when setting the offset in the .rela.plt section.
+        Sun forgot to read their own ABI and copied elf32-sparc behaviour,
+        thus .plt[4] has corresponding .rela.plt[0] and so on.  */
+
       bfd_elf64_swap_reloca_out (output_bfd, &rela,
                                 ((Elf64_External_Rela *) srela->contents
-                                 + h->plt.offset));
+                                 + (h->plt.offset - 4)));
 
       if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
        {
@@ -2913,25 +2929,26 @@ sparc64_elf_merge_private_bfd_data (ibfd, obfd)
   else                                  /* Incompatible flags */
     {
       error = false;
-  
+
+#define EF_SPARC_ISA_EXTENSIONS \
+  (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3 | EF_SPARC_HAL_R1)
+
       if ((ibfd->flags & DYNAMIC) != 0)
        {
          /* We don't want dynamic objects memory ordering and
             architecture to have any role. That's what dynamic linker
             should do.  */
-         new_flags &= ~(EF_SPARCV9_MM | EF_SPARC_SUN_US1 | EF_SPARC_HAL_R1);
+         new_flags &= ~(EF_SPARCV9_MM | EF_SPARC_ISA_EXTENSIONS);
          new_flags |= (old_flags
-                       & (EF_SPARCV9_MM
-                          | EF_SPARC_SUN_US1
-                          | EF_SPARC_HAL_R1));
+                       & (EF_SPARCV9_MM | EF_SPARC_ISA_EXTENSIONS));
        }
       else
        {
          /* Choose the highest architecture requirements.  */
-         old_flags |= (new_flags & (EF_SPARC_SUN_US1 | EF_SPARC_HAL_R1));
-         new_flags |= (old_flags & (EF_SPARC_SUN_US1 | EF_SPARC_HAL_R1));
-         if ((old_flags & (EF_SPARC_SUN_US1 | EF_SPARC_HAL_R1))
-             == (EF_SPARC_SUN_US1 | EF_SPARC_HAL_R1))
+         old_flags |= (new_flags & EF_SPARC_ISA_EXTENSIONS);
+         new_flags |= (old_flags & EF_SPARC_ISA_EXTENSIONS);
+         if ((old_flags & (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3))
+             && (old_flags & EF_SPARC_HAL_R1))
            {
              error = true;
              (*_bfd_error_handler)
@@ -3004,8 +3021,10 @@ sparc64_elf_object_p (abfd)
      bfd *abfd;
 {
   unsigned long mach = bfd_mach_sparc_v9;
-  
-  if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US1)
+
+  if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US3)
+    mach = bfd_mach_sparc_v9b;
+  else if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US1)
     mach = bfd_mach_sparc_v9a;
   return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, mach);
 }