/* SPARC-specific support for 32-bit ELF
- Copyright (C) 1993, 94, 95, 96, 97, 98, 99, 2000, 2001
+ Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
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_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_REV32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_REV32", false,0,0xffffffff,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),
};
static reloc_howto_type elf32_sparc_vtinherit_howto =
HOWTO (R_SPARC_GNU_VTINHERIT, 0,2,0,false,0,complain_overflow_dont, NULL, "R_SPARC_GNU_VTINHERIT", false,0, 0, false);
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, },
{ BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT },
{ BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE },
{ BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 },
- /* ??? Doesn't dwarf use this? */
-/*{ BFD_RELOC_SPARC_UA32, R_SPARC_UA32 }, not used?? */
- {BFD_RELOC_SPARC_10, R_SPARC_10},
- {BFD_RELOC_SPARC_11, R_SPARC_11},
- {BFD_RELOC_SPARC_64, R_SPARC_64},
- {BFD_RELOC_SPARC_OLO10, R_SPARC_OLO10},
- {BFD_RELOC_SPARC_HH22, R_SPARC_HH22},
- {BFD_RELOC_SPARC_HM10, R_SPARC_HM10},
- {BFD_RELOC_SPARC_LM22, R_SPARC_LM22},
- {BFD_RELOC_SPARC_PC_HH22, R_SPARC_PC_HH22},
- {BFD_RELOC_SPARC_PC_HM10, R_SPARC_PC_HM10},
- {BFD_RELOC_SPARC_PC_LM22, R_SPARC_PC_LM22},
- {BFD_RELOC_SPARC_WDISP16, R_SPARC_WDISP16},
- {BFD_RELOC_SPARC_WDISP19, R_SPARC_WDISP19},
- {BFD_RELOC_SPARC_7, R_SPARC_7},
- {BFD_RELOC_SPARC_5, R_SPARC_5},
- {BFD_RELOC_SPARC_6, R_SPARC_6},
- {BFD_RELOC_SPARC_REV32, R_SPARC_REV32 },
- {BFD_RELOC_VTABLE_INHERIT, R_SPARC_GNU_VTINHERIT},
- {BFD_RELOC_VTABLE_ENTRY, R_SPARC_GNU_VTENTRY},
+ { BFD_RELOC_SPARC_UA16, R_SPARC_UA16 },
+ { BFD_RELOC_SPARC_UA32, R_SPARC_UA32 },
+ { BFD_RELOC_SPARC_UA64, R_SPARC_UA64 },
+ { BFD_RELOC_SPARC_10, R_SPARC_10 },
+ { BFD_RELOC_SPARC_11, R_SPARC_11 },
+ { BFD_RELOC_SPARC_64, R_SPARC_64 },
+ { BFD_RELOC_SPARC_OLO10, R_SPARC_OLO10 },
+ { BFD_RELOC_SPARC_HH22, R_SPARC_HH22 },
+ { BFD_RELOC_SPARC_HM10, R_SPARC_HM10 },
+ { BFD_RELOC_SPARC_LM22, R_SPARC_LM22 },
+ { BFD_RELOC_SPARC_PC_HH22, R_SPARC_PC_HH22 },
+ { BFD_RELOC_SPARC_PC_HM10, R_SPARC_PC_HM10 },
+ { BFD_RELOC_SPARC_PC_LM22, R_SPARC_PC_LM22 },
+ { BFD_RELOC_SPARC_WDISP16, R_SPARC_WDISP16 },
+ { BFD_RELOC_SPARC_WDISP19, R_SPARC_WDISP19 },
+ { BFD_RELOC_SPARC_7, R_SPARC_7 },
+ { BFD_RELOC_SPARC_5, R_SPARC_5 },
+ { BFD_RELOC_SPARC_6, R_SPARC_6 },
+ { BFD_RELOC_SPARC_REV32, R_SPARC_REV32 },
+ { BFD_RELOC_VTABLE_INHERIT, R_SPARC_GNU_VTINHERIT },
+ { BFD_RELOC_VTABLE_ENTRY, R_SPARC_GNU_VTENTRY },
};
static reloc_howto_type *
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_22:
case R_SPARC_13:
case R_SPARC_LO10:
+ case R_SPARC_UA16:
case R_SPARC_UA32:
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_22
|| r_type == R_SPARC_13
|| r_type == R_SPARC_LO10
+ || r_type == R_SPARC_UA16
|| r_type == R_SPARC_UA32
|| ((r_type == R_SPARC_PC10
|| r_type == R_SPARC_PC22)
}
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_22:
case R_SPARC_13:
case R_SPARC_LO10:
+ case R_SPARC_UA16:
case R_SPARC_UA32:
- 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. */
/* Mark the symbol as undefined, rather than as defined in
the .plt section. Leave the value alone. */
sym->st_shndx = SHN_UNDEF;
+ /* If the symbol is weak, we do need to clear the value.
+ Otherwise, the PLT entry would provide a definition for
+ the symbol even if the symbol wasn't defined anywhere,
+ and so the symbol would never be NULL. */
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK)
+ == 0)
+ sym->st_value = 0;
}
}
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