static void sparc64_elf_symbol_processing
PARAMS ((bfd *, asymbol *));
-static boolean sparc64_elf_copy_private_bfd_data
- PARAMS ((bfd *, bfd *));
static boolean sparc64_elf_merge_private_bfd_data
PARAMS ((bfd *, bfd *));
static long sparc64_elf_canonicalize_dynamic_reloc
PARAMS ((bfd *, arelent **, asymbol **));
static void sparc64_elf_write_relocs PARAMS ((bfd *, asection *, PTR));
-static enum elf_reloc_type_class sparc64_elf_reloc_type_class PARAMS ((int));
+static enum elf_reloc_type_class sparc64_elf_reloc_type_class
+ PARAMS ((const Elf_Internal_Rela *));
\f
/* The relocation "howto" table. */
HOWTO(R_SPARC_32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_32", false,0,0xffffffff,true),
HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP8", false,0,0x000000ff,true),
HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP16", false,0,0x0000ffff,true),
- HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP32", false,0,0x00ffffff,true),
+ HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP32", false,0,0xffffffff,true),
HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP30", false,0,0x3fffffff,true),
HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP22", false,0,0x003fffff,true),
HOWTO(R_SPARC_HI22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HI22", false,0,0x003fffff,true),
HOWTO(R_SPARC_RELATIVE, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_RELATIVE",false,0,0x00000000,true),
HOWTO(R_SPARC_UA32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_UA32", false,0,0xffffffff,true),
#ifndef SPARC64_OLD_RELOCS
+ HOWTO(R_SPARC_PLT32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PLT32", false,0,0xffffffff,true),
/* These aren't implemented yet. */
- HOWTO(R_SPARC_PLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_PLT32", false,0,0x00000000,true),
HOWTO(R_SPARC_HIPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_HIPLT22", false,0,0x00000000,true),
HOWTO(R_SPARC_LOPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_LOPLT10", false,0,0x00000000,true),
HOWTO(R_SPARC_PCPLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_PCPLT32", false,0,0x00000000,true),
HOWTO(R_SPARC_5, 0,2, 5,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_5", false,0,0x0000001f,true),
HOWTO(R_SPARC_6, 0,2, 6,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_6", false,0,0x0000003f,true),
HOWTO(R_SPARC_DISP64, 0,4,64,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP64", false,0,MINUS_ONE, true),
- HOWTO(R_SPARC_PLT64, 0,4,64,false,0,complain_overflow_bitfield,sparc_elf_notsup_reloc, "R_SPARC_PLT64", false,0,MINUS_ONE, false),
+ HOWTO(R_SPARC_PLT64, 0,4,64,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PLT64", false,0,MINUS_ONE, true),
HOWTO(R_SPARC_HIX22, 0,4, 0,false,0,complain_overflow_bitfield,sparc_elf_hix22_reloc, "R_SPARC_HIX22", false,0,MINUS_ONE, false),
HOWTO(R_SPARC_LOX10, 0,4, 0,false,0,complain_overflow_dont, sparc_elf_lox10_reloc, "R_SPARC_LOX10", false,0,MINUS_ONE, false),
HOWTO(R_SPARC_H44, 22,2,22,false,0,complain_overflow_unsigned,bfd_elf_generic_reloc, "R_SPARC_H44", false,0,0x003fffff,false),
{
{ BFD_RELOC_NONE, R_SPARC_NONE, },
{ BFD_RELOC_16, R_SPARC_16, },
+ { BFD_RELOC_16_PCREL, R_SPARC_DISP16 },
{ BFD_RELOC_8, R_SPARC_8 },
{ BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
{ BFD_RELOC_CTOR, R_SPARC_64 },
{ BFD_RELOC_HI22, R_SPARC_HI22 },
{ BFD_RELOC_LO10, R_SPARC_LO10, },
{ BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 },
+ { BFD_RELOC_64_PCREL, R_SPARC_DISP64 },
{ BFD_RELOC_SPARC22, R_SPARC_22 },
{ BFD_RELOC_SPARC13, R_SPARC_13 },
{ BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 },
{ BFD_RELOC_SPARC_5, R_SPARC_5 },
{ BFD_RELOC_SPARC_6, R_SPARC_6 },
{ BFD_RELOC_SPARC_DISP64, R_SPARC_DISP64 },
+#ifndef SPARC64_OLD_RELOCS
+ { BFD_RELOC_SPARC_PLT32, R_SPARC_PLT32 },
+#endif
{ BFD_RELOC_SPARC_PLT64, R_SPARC_PLT64 },
{ BFD_RELOC_SPARC_HIX22, R_SPARC_HIX22 },
{ BFD_RELOC_SPARC_LOX10, R_SPARC_LOX10 },
entry = contents + i*PLT_ENTRY_SIZE + j*4*6;
ptr = contents + i*PLT_ENTRY_SIZE + block*4*6 + j*8;
- /* ldx [%o7 + ptr - entry+4], %g1 */
- ldx = 0xc25be000 | ((ptr - entry+4) & 0x1fff);
+ /* ldx [%o7 + ptr - (entry+4)], %g1 */
+ ldx = 0xc25be000 | ((ptr - (entry+4)) & 0x1fff);
/* mov %o7,%g5
call .+8
}
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
- break;
-
+ if (ELF64_R_TYPE_ID (rel->r_info) != R_SPARC_PLT32
+ && ELF64_R_TYPE_ID (rel->r_info) != R_SPARC_PLT64)
+ break;
+ /* Fall through. */
case R_SPARC_PC10:
case R_SPARC_PC22:
case R_SPARC_PC_HH22:
default:
(*_bfd_error_handler) (_("%s: check_relocs: unhandled reloc type %d"),
- bfd_get_filename(abfd),
+ bfd_archive_filename (abfd),
ELF64_R_TYPE_ID (rel->r_info));
return false;
}
asection **secp ATTRIBUTE_UNUSED;
bfd_vma *valp ATTRIBUTE_UNUSED;
{
- static char *stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
+ static const char *const stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER)
{
default:
(*_bfd_error_handler)
(_("%s: Only registers %%g[2367] can be declared using STT_REGISTER"),
- bfd_get_filename (abfd));
+ bfd_archive_filename (abfd));
return false;
}
if (p->name != NULL && strcmp (p->name, *namep))
{
(*_bfd_error_handler)
- (_("Register %%g%d used incompatibly: "
- "previously declared in %s to %s, in %s redefined to %s"),
- (int)sym->st_value,
- bfd_get_filename (p->abfd), *p->name ? p->name : "#scratch",
- bfd_get_filename (abfd), **namep ? *namep : "#scratch");
+ (_("Register %%g%d used incompatibly: %s in %s, previously %s in %s"),
+ (int) sym->st_value,
+ **namep ? *namep : "#scratch", bfd_archive_filename (abfd),
+ *p->name ? p->name : "#scratch", bfd_archive_filename (p->abfd));
return false;
}
{
unsigned char type = h->type;
- if (type > STT_FUNC) type = 0;
+ if (type > STT_FUNC)
+ type = 0;
(*_bfd_error_handler)
- (_("Symbol `%s' has differing types: "
- "previously %s, REGISTER in %s"),
- *namep, stt_types [type], bfd_get_filename (abfd));
+ (_("Symbol `%s' has differing types: REGISTER in %s, previously %s in %s"),
+ *namep, bfd_archive_filename (abfd),
+ stt_types[type], bfd_archive_filename (p->abfd));
return false;
}
{
unsigned char type = ELF_ST_TYPE (sym->st_info);
- if (type > STT_FUNC) type = 0;
+ if (type > STT_FUNC)
+ type = 0;
(*_bfd_error_handler)
- (_("Symbol `%s' has differing types: "
- "REGISTER in %s, %s in %s"),
- *namep, bfd_get_filename (p->abfd), stt_types [type],
- bfd_get_filename (abfd));
+ (_("Symbol `%s' has differing types: %s in %s, previously REGISTER in %s"),
+ *namep, stt_types[type], bfd_archive_filename (abfd),
+ bfd_archive_filename (p->abfd));
return false;
}
}
int reg;
struct sparc64_elf_app_reg * app_regs;
- struct bfd_strtab_hash *dynstr;
+ struct elf_strtab_hash *dynstr;
struct elf_link_hash_table *eht = elf_hash_table (info);
if (!info->shared)
entry->isym.st_size = 0;
if (*app_regs [reg].name != '\0')
entry->isym.st_name
- = _bfd_stringtab_add (dynstr, app_regs[reg].name, true, false);
+ = _bfd_elf_strtab_add (dynstr, app_regs[reg].name, false);
else
entry->isym.st_name = 0;
entry->isym.st_other = 0;
return true;
}
\f
+/* This is the condition under which finish_dynamic_symbol will be called
+ from elflink.h. If elflink.h doesn't call our finish_dynamic_symbol
+ routine, we'll need to do something about initializing any .plt and
+ .got entries in relocate_section. */
+#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
+ ((DYN) \
+ && ((INFO)->shared \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
+ && ((H)->dynindx != -1 \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
+
/* Relocate a SPARC64 ELF section. */
static boolean
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
asection *sec;
- bfd_vma relocation;
+ bfd_vma relocation, off;
bfd_reloc_status_type r;
+ boolean is_plt = false;
+ boolean unresolved_reloc;
r_type = ELF64_R_TYPE_ID (rel->r_info);
if (r_type < 0 || r_type >= (int) R_SPARC_max_std)
h = NULL;
sym = NULL;
sec = NULL;
+ unresolved_reloc = false;
if (r_symndx < symtab_hdr->sh_info)
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
- relocation = (sec->output_section->vma
- + sec->output_offset
- + sym->st_value);
+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
}
else
{
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ relocation = 0;
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
- boolean skip_it = false;
sec = h->root.u.def.section;
-
- switch (r_type)
- {
- case R_SPARC_WPLT30:
- case R_SPARC_PLT32:
- case R_SPARC_HIPLT22:
- case R_SPARC_LOPLT10:
- case R_SPARC_PCPLT32:
- case R_SPARC_PCPLT22:
- case R_SPARC_PCPLT10:
- case R_SPARC_PLT64:
- if (h->plt.offset != (bfd_vma) -1)
- skip_it = true;
- break;
-
- case R_SPARC_GOT10:
- case R_SPARC_GOT13:
- case R_SPARC_GOT22:
- if (elf_hash_table(info)->dynamic_sections_created
- && (!info->shared
- || (!info->symbolic && h->dynindx != -1)
- || !(h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR)))
- skip_it = true;
- break;
-
- case R_SPARC_PC10:
- case R_SPARC_PC22:
- case R_SPARC_PC_HH22:
- case R_SPARC_PC_HM10:
- case R_SPARC_PC_LM22:
- if (!strcmp(h->root.root.string, "_GLOBAL_OFFSET_TABLE_"))
- break;
- /* FALLTHRU */
-
- case R_SPARC_8:
- case R_SPARC_16:
- case R_SPARC_32:
- case R_SPARC_DISP8:
- case R_SPARC_DISP16:
- case R_SPARC_DISP32:
- case R_SPARC_WDISP30:
- case R_SPARC_WDISP22:
- case R_SPARC_HI22:
- case R_SPARC_22:
- case R_SPARC_13:
- case R_SPARC_LO10:
- case R_SPARC_UA32:
- case R_SPARC_10:
- case R_SPARC_11:
- case R_SPARC_64:
- case R_SPARC_OLO10:
- case R_SPARC_HH22:
- case R_SPARC_HM10:
- case R_SPARC_LM22:
- case R_SPARC_WDISP19:
- case R_SPARC_WDISP16:
- case R_SPARC_7:
- case R_SPARC_5:
- case R_SPARC_6:
- case R_SPARC_DISP64:
- case R_SPARC_HIX22:
- case R_SPARC_LOX10:
- case R_SPARC_H44:
- case R_SPARC_M44:
- case R_SPARC_L44:
- case R_SPARC_UA64:
- case R_SPARC_UA16:
- if (info->shared
- && ((!info->symbolic && h->dynindx != -1)
- || !(h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR)))
- skip_it = true;
- break;
- }
-
- if (skip_it)
- {
- /* In these cases, we don't need the relocation
- value. We check specially because in some
- obscure cases sec->output_section will be NULL. */
- relocation = 0;
- }
+ if (sec->output_section == NULL)
+ /* Set a flag that will be cleared later if we find a
+ relocation value for this symbol. output_section
+ is typically NULL for symbols satisfied by a shared
+ library. */
+ unresolved_reloc = true;
else
- {
- relocation = (h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
- }
+ relocation = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
}
else if (h->root.type == bfd_link_hash_undefweak)
- relocation = 0;
+ ;
else if (info->shared
&& (!info->symbolic || info->allow_shlib_undefined)
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
- relocation = 0;
+ ;
else
{
if (! ((*info->callbacks->undefined_symbol)
}
}
+ do_dynreloc:
/* When generating a shared object, these relocations are copied
into the output file to be resolved at run time. */
- if (info->shared && (input_section->flags & SEC_ALLOC))
+ if (info->shared && r_symndx != 0 && (input_section->flags & SEC_ALLOC))
{
switch (r_type)
{
case R_SPARC_UA16:
{
Elf_Internal_Rela outrel;
- boolean skip;
+ boolean skip, relocate;
if (sreloc == NULL)
{
}
skip = false;
+ relocate = false;
- if (elf_section_data (input_section)->stab_info == NULL)
- outrel.r_offset = rel->r_offset;
- else
- {
- bfd_vma off;
-
- off = (_bfd_stab_section_offset
- (output_bfd, &elf_hash_table (info)->stab_info,
- input_section,
- &elf_section_data (input_section)->stab_info,
- rel->r_offset));
- if (off == MINUS_ONE)
- skip = true;
- outrel.r_offset = off;
- }
+ outrel.r_offset =
+ _bfd_elf_section_offset (output_bfd, info, input_section,
+ rel->r_offset);
+ if (outrel.r_offset == (bfd_vma) -1)
+ skip = true;
+ else if (outrel.r_offset == (bfd_vma) -2)
+ skip = true, relocate = true;
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
memset (&outrel, 0, sizeof outrel);
/* h->dynindx may be -1 if the symbol was marked to
become local. */
- else if (h != NULL
+ else if (h != NULL && ! is_plt
&& ((! info->symbolic && h->dynindx != -1)
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))
{
long indx;
- if (h == NULL)
+ if (is_plt)
+ sec = splt;
+ else if (h == NULL)
sec = local_sections[r_symndx];
else
{
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;
}
/* This reloc will be computed at runtime, so there's no
need to do anything now. */
- continue;
+ if (! relocate)
+ continue;
}
break;
}
if (h != NULL)
{
- bfd_vma off = h->got.offset;
+ boolean dyn;
+
+ off = h->got.offset;
BFD_ASSERT (off != (bfd_vma) -1);
+ dyn = elf_hash_table (info)->dynamic_sections_created;
- if (! elf_hash_table (info)->dynamic_sections_created
+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
|| (info->shared
- && (info->symbolic || h->dynindx == -1)
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR)))
+ && (info->symbolic
+ || h->dynindx == -1
+ || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
{
/* This is actually a static link, or it is a -Bsymbolic
link and the symbol is defined locally, or the symbol
h->got.offset |= 1;
}
}
- relocation = sgot->output_offset + off - got_base;
+ else
+ unresolved_reloc = false;
}
else
{
- bfd_vma off;
-
BFD_ASSERT (local_got_offsets != NULL);
off = local_got_offsets[r_symndx];
BFD_ASSERT (off != (bfd_vma) -1);
else
bfd_put_64 (output_bfd, relocation, sgot->contents + off);
}
- relocation = sgot->output_offset + off - got_base;
}
+ relocation = sgot->output_offset + off - got_base;
goto do_default;
case R_SPARC_WPLT30:
relocation = (splt->output_section->vma
+ splt->output_offset
+ sparc64_elf_plt_entry_offset (h->plt.offset));
+ unresolved_reloc = false;
if (r_type == R_SPARC_WPLT30)
goto do_wplt30;
+ if (r_type == R_SPARC_PLT32 || r_type == R_SPARC_PLT64)
+ {
+ r_type = r_type == R_SPARC_PLT32 ? R_SPARC_32 : R_SPARC_64;
+ is_plt = true;
+ goto do_dynreloc;
+ }
goto do_default;
case R_SPARC_OLO10:
break;
}
+ if (unresolved_reloc
+ && !(info->shared
+ && (input_section->flags & SEC_DEBUGGING) != 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
+ (*_bfd_error_handler)
+ (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
+ bfd_archive_filename (input_bfd),
+ bfd_get_section_name (input_bfd, input_section),
+ (long) rel->r_offset,
+ h->root.root.string);
+
switch (r)
{
case bfd_reloc_ok:
{
const char *name;
+ /* The Solaris native linker silently disregards
+ overflows. We don't, but this breaks stabs debugging
+ info, whose relocations are only 32-bits wide. Ignore
+ overflows in this case. */
+ if (r_type == R_SPARC_32
+ && (input_section->flags & SEC_DEBUGGING) != 0
+ && strcmp (bfd_section_name (input_bfd, input_section),
+ ".stab") == 0)
+ break;
+
if (h != NULL)
{
if (h->root.type == bfd_link_hash_undefweak
}
static enum elf_reloc_type_class
-sparc64_elf_reloc_type_class (type)
- int type;
+sparc64_elf_reloc_type_class (rela)
+ const Elf_Internal_Rela *rela;
{
- switch (type)
+ switch ((int) ELF64_R_TYPE (rela->r_info))
{
case R_SPARC_RELATIVE:
return reloc_class_relative;
\f
/* Functions for dealing with the e_flags field. */
-/* Copy backend specific data from one object module to another */
-static boolean
-sparc64_elf_copy_private_bfd_data (ibfd, obfd)
- bfd *ibfd, *obfd;
-{
- if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return true;
-
- BFD_ASSERT (!elf_flags_init (obfd)
- || (elf_elfheader (obfd)->e_flags
- == elf_elfheader (ibfd)->e_flags));
-
- elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
- elf_flags_init (obfd) = true;
- return true;
-}
-
/* Merge backend specific data from an object file to the output
object file when linking. */
error = true;
(*_bfd_error_handler)
(_("%s: linking UltraSPARC specific with HAL specific code"),
- bfd_get_filename (ibfd));
+ bfd_archive_filename (ibfd));
}
/* Choose the most restrictive memory ordering. */
old_mm = (old_flags & EF_SPARCV9_MM);
error = true;
(*_bfd_error_handler)
(_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
- bfd_get_filename (ibfd), (long)new_flags, (long)old_flags);
+ bfd_archive_filename (ibfd), (long) new_flags, (long) old_flags);
}
elf_elfheader (obfd)->e_flags = old_flags;
sparc64_elf_print_symbol_all
#define elf_backend_output_arch_syms \
sparc64_elf_output_arch_syms
-#define bfd_elf64_bfd_copy_private_bfd_data \
- sparc64_elf_copy_private_bfd_data
#define bfd_elf64_bfd_merge_private_bfd_data \
sparc64_elf_merge_private_bfd_data