/* SPARC-specific support for ELF
- Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
return bfd_reloc_ok;
}
+/* Handle the WDISP10 reloc. */
+
+static bfd_reloc_status_type
+sparc_elf_wdisp10_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+ PTR data, asection *input_section, bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED)
+{
+ bfd_vma relocation;
+ bfd_vma insn;
+ bfd_reloc_status_type status;
+
+ status = init_insn_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd, &relocation, &insn);
+ if (status != bfd_reloc_other)
+ return status;
+
+ insn &= ~ (bfd_vma) 0x181fe0;
+ insn |= (((relocation >> 2) & 0x300) << 11)
+ | (((relocation >> 2) & 0xff) << 5);
+ bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
+
+ if ((bfd_signed_vma) relocation < - 0x1000
+ || (bfd_signed_vma) relocation > 0xfff)
+ return bfd_reloc_overflow;
+ else
+ return bfd_reloc_ok;
+}
+
/* Handle the HIX22 reloc. */
static bfd_reloc_status_type
HOWTO(R_SPARC_GOTDATA_OP_HIX22,0,2,0,FALSE,0,complain_overflow_bitfield,sparc_elf_hix22_reloc,"R_SPARC_GOTDATA_OP_HIX22",FALSE,0,0x003fffff, FALSE),
HOWTO(R_SPARC_GOTDATA_OP_LOX10,0,2,0,FALSE,0,complain_overflow_dont, sparc_elf_lox10_reloc, "R_SPARC_GOTDATA_OP_LOX10",FALSE,0,0x000003ff, FALSE),
HOWTO(R_SPARC_GOTDATA_OP,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOTDATA_OP",FALSE,0,0x00000000,TRUE),
+ HOWTO(R_SPARC_H34,12,2,22,FALSE,0,complain_overflow_unsigned,bfd_elf_generic_reloc,"R_SPARC_H34",FALSE,0,0x003fffff,FALSE),
+ HOWTO(R_SPARC_SIZE32,0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_SIZE32",FALSE,0,0xffffffff,TRUE),
+ HOWTO(R_SPARC_SIZE64,0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_SIZE64",FALSE,0,MINUS_ONE, TRUE),
+ HOWTO(R_SPARC_WDISP10,2,2,10,TRUE, 0,complain_overflow_signed,sparc_elf_wdisp10_reloc,"R_SPARC_WDISP10",FALSE,0,0x00000000,TRUE),
};
static reloc_howto_type sparc_jmp_irel_howto =
HOWTO(R_SPARC_JMP_IREL, 0,0,00,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_JMP_IREL",FALSE,0,0x00000000,TRUE);
case BFD_RELOC_SPARC_GOTDATA_OP:
return &_bfd_sparc_elf_howto_table[R_SPARC_GOTDATA_OP];
+ case BFD_RELOC_SPARC_H34:
+ return &_bfd_sparc_elf_howto_table[R_SPARC_H34];
+
+ case BFD_RELOC_SPARC_SIZE32:
+ return &_bfd_sparc_elf_howto_table[R_SPARC_SIZE32];
+
+ case BFD_RELOC_SPARC_SIZE64:
+ return &_bfd_sparc_elf_howto_table[R_SPARC_SIZE64];
+
+ case BFD_RELOC_SPARC_WDISP10:
+ return &_bfd_sparc_elf_howto_table[R_SPARC_WDISP10];
+
case BFD_RELOC_SPARC_JMP_IREL:
return &sparc_jmp_irel_howto;
case R_SPARC_WDISP22:
case R_SPARC_WDISP19:
case R_SPARC_WDISP16:
+ case R_SPARC_WDISP10:
case R_SPARC_8:
case R_SPARC_16:
case R_SPARC_32:
case R_SPARC_H44:
case R_SPARC_M44:
case R_SPARC_L44:
+ case R_SPARC_H34:
case R_SPARC_UA64:
if (h != NULL)
h->non_got_ref = 1;
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,
case R_SPARC_WDISP22:
case R_SPARC_WDISP19:
case R_SPARC_WDISP16:
+ case R_SPARC_WDISP10:
case R_SPARC_8:
case R_SPARC_16:
case R_SPARC_32:
case R_SPARC_H44:
case R_SPARC_M44:
case R_SPARC_L44:
+ case R_SPARC_H34:
case R_SPARC_UA64:
if (info->shared)
break;
return TRUE;
}
- if (h->size == 0)
- {
- (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
- h->root.root.string);
- return TRUE;
- }
-
/* We must allocate the symbol in our .dynbss section, which will
become part of the .bss section of the executable. There will be
an entry for this symbol in the .dynsym section. The dynamic
to copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rel.bss section we are going to use. */
- if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
htab->srelbss->size += SPARC_ELF_RELA_BYTES (htab);
h->needs_copy = 1;
}
}
- if (sec != NULL && elf_discarded_section (sec))
+ if (sec != NULL && discarded_section (sec))
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
- rel, relend, howto, contents);
+ rel, 1, relend, howto, 0, contents);
if (info->relocatable)
continue;
case R_SPARC_WDISP22:
case R_SPARC_WDISP19:
case R_SPARC_WDISP16:
+ case R_SPARC_WDISP10:
case R_SPARC_8:
case R_SPARC_16:
case R_SPARC_32:
case R_SPARC_H44:
case R_SPARC_M44:
case R_SPARC_L44:
+ case R_SPARC_H34:
case R_SPARC_UA64:
r_sparc_plt32:
if ((input_section->flags & SEC_ALLOC) == 0
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,
| ((relocation >> 2) & 0x3fff));
bfd_put_32 (input_bfd, x, contents + rel->r_offset);
+ r = bfd_check_overflow (howto->complain_on_overflow,
+ howto->bitsize, howto->rightshift,
+ bfd_arch_bits_per_address (input_bfd),
+ relocation);
+ }
+ else if (r_type == R_SPARC_WDISP10)
+ {
+ bfd_vma x;
+
+ relocation += rel->r_addend;
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset);
+ relocation -= rel->r_offset;
+
+ x = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ x |= ((((relocation >> 2) & 0x300) << 11)
+ | (((relocation >> 2) & 0xff) << 5));
+ bfd_put_32 (input_bfd, x, contents + rel->r_offset);
+
r = bfd_check_overflow (howto->complain_on_overflow,
howto->bitsize, howto->rightshift,
bfd_arch_bits_per_address (input_bfd),
We don't, but this breaks stabs debugging info, whose
relocations are only 32-bits wide. Ignore overflows in
this case and also for discarded entries. */
- if ((r_type == R_SPARC_32 || r_type == R_SPARC_DISP32)
+ if ((r_type == R_SPARC_32
+ || r_type == R_SPARC_UA32
+ || r_type == R_SPARC_DISP32)
&& (((input_section->flags & SEC_DEBUGGING) != 0
&& strcmp (bfd_section_name (input_bfd,
input_section),
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;
+}