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,
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))
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;
}
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,
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;
+}