2012-02-24 Luis Machado <lgustavo@codesourcery>
[deliverable/binutils-gdb.git] / bfd / elfxx-sparc.c
index d72dcba0a3eadd649fdcae4b780bf8943facd510..fe18a62cc99a87f45acdf5f80b3eace521367396 100644 (file)
@@ -1830,6 +1830,20 @@ _bfd_sparc_elf_gc_mark_hook (asection *sec,
   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
 }
 
+static Elf_Internal_Rela *
+sparc_elf_find_reloc_at_ofs (Elf_Internal_Rela *rel,
+                            Elf_Internal_Rela *relend,
+                            bfd_vma offset)
+{
+  while (rel < relend)
+    {
+      if (rel->r_offset == offset)
+       return rel;
+      rel++;
+    }
+  return NULL;
+}
+
 /* Update the got entry reference counts for the section being removed.  */
 bfd_boolean
 _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
@@ -3676,6 +3690,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
          if (! info->shared
              || (r_type == R_SPARC_TLS_GD_CALL && tls_type == GOT_TLS_IE))
            {
+             Elf_Internal_Rela *rel2;
              bfd_vma insn;
 
              if (!info->shared && (h == NULL || h->dynindx == -1))
@@ -3711,7 +3726,26 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
                  continue;
                }
 
-             bfd_put_32 (output_bfd, 0x9001c008, contents + rel->r_offset);
+             /* We cannot just overwrite the delay slot instruction,
+                as it might be what puts the %o0 argument to
+                __tls_get_addr into place.  So we have to transpose
+                the delay slot with the add we patch in.  */
+             insn = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
+             bfd_put_32 (output_bfd, insn,
+                         contents + rel->r_offset);
+             bfd_put_32 (output_bfd, 0x9001c008,
+                         contents + rel->r_offset + 4);
+
+             rel2 = rel;
+             while ((rel2 = sparc_elf_find_reloc_at_ofs (rel2 + 1, relend,
+                                                         rel->r_offset + 4))
+                    != NULL)
+               {
+                 /* If the instruction we moved has a relocation attached to
+                    it, adjust the offset so that it will apply to the correct
+                    instruction.  */
+                 rel2->r_offset -= 4;
+               }
              continue;
            }
 
@@ -3794,7 +3828,9 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
         not process them.  */
       if (unresolved_reloc
          && !((input_section->flags & SEC_DEBUGGING) != 0
-              && h->def_dynamic))
+              && h->def_dynamic)
+         && _bfd_elf_section_offset (output_bfd, info, input_section,
+                                     rel->r_offset) != (bfd_vma) -1)
        (*_bfd_error_handler)
          (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
           input_bfd,
@@ -4754,3 +4790,38 @@ _bfd_sparc_elf_plt_sym_val (bfd_vma i, const asection *plt, const arelent *rel)
   else
     return rel->address;
 }
+
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+bfd_boolean
+_bfd_sparc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+{
+  obj_attribute *in_attr, *in_attrs;
+  obj_attribute *out_attr, *out_attrs;
+
+  if (!elf_known_obj_attributes_proc (obfd)[0].i)
+    {
+      /* This is the first object.  Copy the attributes.  */
+      _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
+      /* Use the Tag_null value to indicate the attributes have been
+        initialized.  */
+      elf_known_obj_attributes_proc (obfd)[0].i = 1;
+
+      return TRUE;
+    }
+
+  in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
+  out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
+
+  in_attr = &in_attrs[Tag_GNU_Sparc_HWCAPS];
+  out_attr = &out_attrs[Tag_GNU_Sparc_HWCAPS];
+
+  out_attr->i |= in_attr->i;
+
+  /* Merge Tag_compatibility attributes and any common GNU ones.  */
+  _bfd_elf_merge_object_attributes (ibfd, obfd);
+
+  return TRUE;
+}
This page took 0.02445 seconds and 4 git commands to generate.