PARAMS ((bfd *));
static void elf32_sparc_final_write_processing
PARAMS ((bfd *, boolean));
+static enum elf_reloc_type_class elf32_sparc_reloc_type_class
+ PARAMS ((const Elf_Internal_Rela *));
+static asection * elf32_sparc_gc_mark_hook
+ PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ struct elf_link_hash_entry *, Elf_Internal_Sym *));
+static boolean elf32_sparc_gc_sweep_hook
+ PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ const Elf_Internal_Rela *));
\f
/* The relocation "howto" table. */
HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true),
HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true),
HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true),
- HOWTO(R_SPARC_UA64, 0,4,64,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_UA64", false,0,(~ (bfd_vma)0), true),
+ HOWTO(R_SPARC_UA64, 0,0, 0,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_UA64", false,0,0x00000000,true),
HOWTO(R_SPARC_UA16, 0,1,16,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_UA16", false,0,0x0000ffff,true),
HOWTO(R_SPARC_REV32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_REV32", false,0,0xffffffff,true),
};
unsigned char elf_reloc_val;
};
-static CONST struct elf_reloc_map sparc_reloc_map[] =
+static const struct elf_reloc_map sparc_reloc_map[] =
{
{ BFD_RELOC_NONE, R_SPARC_NONE, },
{ BFD_RELOC_16, R_SPARC_16, },
symbol. */
if (local_got_offsets == NULL)
{
- size_t size;
+ bfd_size_type size;
register unsigned int i;
- size = symtab_hdr->sh_info * sizeof (bfd_vma);
+ size = symtab_hdr->sh_info;
+ size *= sizeof (bfd_vma);
local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
if (local_got_offsets == NULL)
return false;
case R_SPARC_LO10:
case R_SPARC_UA16:
case R_SPARC_UA32:
- case R_SPARC_UA64:
if (h != NULL)
h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
- if (info->shared)
+ if (info->shared && (sec->flags & SEC_ALLOC))
{
/* When creating a shared object, we must copy these
relocs into the output file. We create a reloc
|| ! bfd_set_section_alignment (dynobj, sreloc, 2))
return false;
}
+ if (sec->flags & SEC_READONLY)
+ info->flags |= DF_TEXTREL;
}
sreloc->_raw_size += sizeof (Elf32_External_Rela);
static boolean
elf32_sparc_size_dynamic_sections (output_bfd, info)
- bfd *output_bfd;
+ bfd *output_bfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info;
{
bfd *dynobj;
asection *s;
- boolean reltext;
boolean relplt;
dynobj = elf_hash_table (info)->dynobj;
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
memory for them. */
- reltext = false;
relplt = false;
for (s = dynobj->sections; s != NULL; s = s->next)
{
}
else
{
- const char *outname;
- asection *target;
-
- /* If this relocation section applies to a read only
- section, then we probably need a DT_TEXTREL entry. */
- outname = bfd_get_section_name (output_bfd,
- s->output_section);
- target = bfd_get_section_by_name (output_bfd, outname + 5);
- if (target != NULL
- && (target->flags & SEC_READONLY) != 0
- && (target->flags & SEC_ALLOC) != 0)
- reltext = true;
-
if (strcmp (name, ".rela.plt") == 0)
relplt = true;
must add the entries now so that we get the correct size for
the .dynamic section. The DT_DEBUG entry is filled in by the
dynamic linker and used by the debugger. */
- if (! info->shared)
+#define add_dynamic_entry(TAG, VAL) \
+ bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
+ if (!info->shared)
{
- if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
+ if (!add_dynamic_entry (DT_DEBUG, 0))
return false;
}
if (relplt)
{
- if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)
- || ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
- || ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
- || ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
+ if (!add_dynamic_entry (DT_PLTGOT, 0)
+ || !add_dynamic_entry (DT_PLTRELSZ, 0)
+ || !add_dynamic_entry (DT_PLTREL, DT_RELA)
+ || !add_dynamic_entry (DT_JMPREL, 0))
return false;
}
- if (! bfd_elf32_add_dynamic_entry (info, DT_RELA, 0)
- || ! bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0)
- || ! bfd_elf32_add_dynamic_entry (info, DT_RELAENT,
- sizeof (Elf32_External_Rela)))
+ if (!add_dynamic_entry (DT_RELA, 0)
+ || !add_dynamic_entry (DT_RELASZ, 0)
+ || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
return false;
- if (reltext)
+ if (info->flags & DF_TEXTREL)
{
- if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
+ if (!add_dynamic_entry (DT_TEXTREL, 0))
return false;
- info->flags |= DF_TEXTREL;
}
}
+#undef add_dynamic_entry
return true;
}
|| r_type == R_SPARC_LO10
|| r_type == R_SPARC_UA16
|| r_type == R_SPARC_UA32
- || r_type == R_SPARC_UA64
|| ((r_type == R_SPARC_PC10
|| r_type == R_SPARC_PC22)
&& strcmp (h->root.root.string,
}
else if (h->root.type == bfd_link_hash_undefweak)
relocation = 0;
- else if (info->shared && !info->symbolic
+ else if (info->shared
+ && (!info->symbolic || info->allow_shlib_undefined)
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
relocation = 0;
case R_SPARC_LO10:
case R_SPARC_UA16:
case R_SPARC_UA32:
- case R_SPARC_UA64:
- if (info->shared)
+ if (info->shared && (input_section->flags & SEC_ALLOC))
{
Elf_Internal_Rela outrel;
boolean skip;
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
+ /* Optimize unaligned reloc usage now that we know where
+ it finally resides. */
+ switch (r_type)
+ {
+ case R_SPARC_16:
+ if (outrel.r_offset & 1)
+ r_type = R_SPARC_UA16;
+ break;
+ case R_SPARC_UA16:
+ if (!(outrel.r_offset & 1))
+ r_type = R_SPARC_16;
+ break;
+ case R_SPARC_32:
+ if (outrel.r_offset & 3)
+ r_type = R_SPARC_UA32;
+ break;
+ case R_SPARC_UA32:
+ if (!(outrel.r_offset & 3))
+ r_type = R_SPARC_32;
+ break;
+ }
+
if (skip)
memset (&outrel, 0, sizeof outrel);
/* h->dynindx may be -1 if the symbol was marked to
}
else
{
- if (r_type == R_SPARC_32)
+ if (r_type == R_SPARC_32 || r_type == R_SPARC_UA32)
{
outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);
outrel.r_addend = relocation + rel->r_addend;
BFD_FAIL ();
(*_bfd_error_handler)
(_("%s: probably compiled without -fPIC?"),
- bfd_get_filename (input_bfd));
+ bfd_archive_filename (input_bfd));
bfd_set_error (bfd_error_bad_value);
return false;
}
++sreloc->reloc_count;
/* This reloc will be computed at runtime, so there's no
- need to do anything now, unless this is a RELATIVE
- reloc in an unallocated section. */
- if (skip
- || (input_section->flags & SEC_ALLOC) != 0
- || ELF32_R_TYPE (outrel.r_info) != R_SPARC_RELATIVE)
- continue;
+ need to do anything now. */
+ continue;
}
break;
|| reg == G0 || reg == O7)
break;
- bfd_put_32 (input_bfd, INSN_NOP,
+ bfd_put_32 (input_bfd, (bfd_vma) INSN_NOP,
contents + rel->r_offset + 4);
}
(PLT_ENTRY_WORD1
+ (((- (h->plt.offset + 4)) >> 2) & 0x3fffff)),
splt->contents + h->plt.offset + 4);
- bfd_put_32 (output_bfd, PLT_ENTRY_WORD2,
+ bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD2,
splt->contents + h->plt.offset + 8);
/* Fill in the entry in the .rela.plt section. */
rela.r_offset = (sgot->output_section->vma
+ sgot->output_offset
- + (h->got.offset &~ 1));
+ + (h->got.offset &~ (bfd_vma) 1));
/* If this is a -Bsymbolic link, and the symbol is defined
locally, we just want to emit a RELATIVE reloc. Likewise if
if (splt->_raw_size > 0)
{
memset (splt->contents, 0, 4 * PLT_ENTRY_SIZE);
- bfd_put_32 (output_bfd, SPARC_NOP,
+ bfd_put_32 (output_bfd, (bfd_vma) SPARC_NOP,
splt->contents + splt->_raw_size - 4);
}
error = true;
(*_bfd_error_handler)
(_("%s: compiled for a 64 bit system and target is 32 bit"),
- bfd_get_filename (ibfd));
+ bfd_archive_filename (ibfd));
}
else if ((ibfd->flags & DYNAMIC) == 0)
{
{
(*_bfd_error_handler)
(_("%s: linking little endian files with big endian files"),
- bfd_get_filename (ibfd));
+ bfd_archive_filename (ibfd));
error = true;
}
previous_ibfd_e_flags = elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA;
}
else if (elf_elfheader (abfd)->e_flags & EF_SPARC_LEDATA)
return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
- bfd_mach_sparc_sparclite_le);
+ bfd_mach_sparc_sparclite_le);
else
return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc);
}
break;
}
}
+
+static enum elf_reloc_type_class
+elf32_sparc_reloc_type_class (rela)
+ const Elf_Internal_Rela *rela;
+{
+ switch ((int) ELF32_R_TYPE (rela->r_info))
+ {
+ case R_SPARC_RELATIVE:
+ return reloc_class_relative;
+ case R_SPARC_JMP_SLOT:
+ return reloc_class_plt;
+ case R_SPARC_COPY:
+ return reloc_class_copy;
+ default:
+ return reloc_class_normal;
+ }
+}
\f
#define TARGET_BIG_SYM bfd_elf32_sparc_vec
#define TARGET_BIG_NAME "elf32-sparc"
elf32_sparc_final_write_processing
#define elf_backend_gc_mark_hook elf32_sparc_gc_mark_hook
#define elf_backend_gc_sweep_hook elf32_sparc_gc_sweep_hook
+#define elf_backend_reloc_type_class elf32_sparc_reloc_type_class
#define elf_backend_can_gc_sections 1
#define elf_backend_want_got_plt 0