/* SPARC-specific support for ELF
- Copyright 2005, 2006 Free Software Foundation, Inc.
+ Copyright 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
/* This file handles functionality common to the different SPARC ABI's. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "libiberty.h"
HOWTO(R_SPARC_TLS_DTPOFF32,0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_TLS_DTPOFF32",FALSE,0,0xffffffff,TRUE),
HOWTO(R_SPARC_TLS_DTPOFF64,0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_TLS_DTPOFF64",FALSE,0,MINUS_ONE,TRUE),
HOWTO(R_SPARC_TLS_TPOFF32,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_TPOFF32",FALSE,0,0x00000000,TRUE),
- HOWTO(R_SPARC_TLS_TPOFF64,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_TPOFF64",FALSE,0,0x00000000,TRUE)
+ HOWTO(R_SPARC_TLS_TPOFF64,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_TPOFF64",FALSE,0,0x00000000,TRUE),
+ HOWTO(R_SPARC_GOTDATA_HIX22,0,2,0,FALSE,0,complain_overflow_bitfield,sparc_elf_hix22_reloc,"R_SPARC_GOTDATA_HIX22",FALSE,0,0x003fffff, FALSE),
+ HOWTO(R_SPARC_GOTDATA_LOX10,0,2,0,FALSE,0,complain_overflow_dont, sparc_elf_lox10_reloc, "R_SPARC_GOTDATA_LOX10",FALSE,0,0x000003ff, FALSE),
+ 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),
};
static reloc_howto_type 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);
{ BFD_RELOC_SPARC_H44, R_SPARC_H44 },
{ BFD_RELOC_SPARC_M44, R_SPARC_M44 },
{ BFD_RELOC_SPARC_L44, R_SPARC_L44 },
+ { BFD_RELOC_SPARC_GOTDATA_HIX22, R_SPARC_GOTDATA_HIX22 },
+ { BFD_RELOC_SPARC_GOTDATA_LOX10, R_SPARC_GOTDATA_LOX10 },
+ { BFD_RELOC_SPARC_GOTDATA_OP_HIX22, R_SPARC_GOTDATA_OP_HIX22 },
+ { BFD_RELOC_SPARC_GOTDATA_OP_LOX10, R_SPARC_GOTDATA_OP_LOX10 },
+ { BFD_RELOC_SPARC_GOTDATA_OP, R_SPARC_GOTDATA_OP },
{ BFD_RELOC_SPARC_REGISTER, R_SPARC_REGISTER },
{ BFD_RELOC_VTABLE_INHERIT, R_SPARC_GNU_VTINHERIT },
{ BFD_RELOC_VTABLE_ENTRY, R_SPARC_GNU_VTENTRY },
return NULL;
}
+reloc_howto_type *
+_bfd_sparc_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < (sizeof (_bfd_sparc_elf_howto_table)
+ / sizeof (_bfd_sparc_elf_howto_table[0]));
+ i++)
+ if (_bfd_sparc_elf_howto_table[i].name != NULL
+ && strcasecmp (_bfd_sparc_elf_howto_table[i].name, r_name) == 0)
+ return &_bfd_sparc_elf_howto_table[i];
+
+ if (strcasecmp (sparc_vtinherit_howto.name, r_name) == 0)
+ return &sparc_vtinherit_howto;
+ if (strcasecmp (sparc_vtentry_howto.name, r_name) == 0)
+ return &sparc_vtentry_howto;
+ if (strcasecmp (sparc_rev32_howto.name, r_name) == 0)
+ return &sparc_rev32_howto;
+
+ return NULL;
+}
+
reloc_howto_type *
_bfd_sparc_elf_info_to_howto_ptr (unsigned int r_type)
{
#define _bfd_sparc_elf_local_got_tls_type(abfd) \
(_bfd_sparc_elf_tdata (abfd)->local_got_tls_type)
+#define is_sparc_elf(bfd) \
+ (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
+ && elf_tdata (bfd) != NULL \
+ && elf_object_id (bfd) == SPARC_ELF_TDATA)
+
bfd_boolean
_bfd_sparc_elf_mkobject (bfd *abfd)
{
- bfd_size_type amt = sizeof (struct _bfd_sparc_elf_obj_tdata);
- abfd->tdata.any = bfd_zalloc (abfd, amt);
- if (abfd->tdata.any == NULL)
- return FALSE;
- return TRUE;
+ return bfd_elf_allocate_object (abfd, sizeof (struct _bfd_sparc_elf_obj_tdata),
+ SPARC_ELF_TDATA);
}
static void
}
static void
-sparc_elf_append_rela_64 (bfd *abfd ATTRIBUTE_UNUSED,
- asection *s ATTRIBUTE_UNUSED,
- Elf_Internal_Rela *rel ATTRIBUTE_UNUSED)
-{
-#ifdef BFD64
- Elf64_External_Rela *loc64;
-
- loc64 = (Elf64_External_Rela *) s->contents;
- loc64 += s->reloc_count++;
- bfd_elf64_swap_reloca_out (abfd, rel, (bfd_byte *) loc64);
-#endif
-}
-
-static void
-sparc_elf_append_rela_32 (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
+sparc_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
{
- Elf32_External_Rela *loc32;
+ const struct elf_backend_data *bed;
+ bfd_byte *loc;
- loc32 = (Elf32_External_Rela *) s->contents;
- loc32 += s->reloc_count++;
- bfd_elf32_swap_reloca_out (abfd, rel, (bfd_byte *) loc32);
+ bed = get_elf_backend_data (abfd);
+ loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela);
+ bed->s->swap_reloca_out (abfd, rel, loc);
}
static bfd_vma
#define SPARC_ELF_PUT_WORD(htab, bfd, val, ptr) \
htab->put_word(bfd, val, ptr)
-#define SPARC_ELF_APPEND_RELA(htab, bfd, sec, rela) \
- htab->append_rela(bfd, sec, rela)
-
#define SPARC_ELF_R_INFO(htab, in_rel, index, type) \
htab->r_info(in_rel, index, type)
if (ABI_64_P (abfd))
{
ret->put_word = sparc_put_word_64;
- ret->append_rela = sparc_elf_append_rela_64;
ret->r_info = sparc_elf_r_info_64;
ret->r_symndx = sparc_elf_r_symndx_64;
ret->dtpoff_reloc = R_SPARC_TLS_DTPOFF64;
else
{
ret->put_word = sparc_put_word_32;
- ret->append_rela = sparc_elf_append_rela_32;
ret->r_info = sparc_elf_r_info_32;
ret->r_symndx = sparc_elf_r_symndx_32;
ret->dtpoff_reloc = R_SPARC_TLS_DTPOFF32;
return TRUE;
htab = _bfd_sparc_elf_hash_table (info);
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ symtab_hdr = &elf_symtab_hdr (abfd);
sym_hashes = elf_sym_hashes (abfd);
local_got_offsets = elf_local_got_offsets (abfd);
num_relocs = NUM_SHDR_ENTRIES (& elf_section_data (sec)->rel_hdr);
else
num_relocs = sec->reloc_count;
+
+ BFD_ASSERT (is_sparc_elf (abfd) || num_relocs == 0);
+
rel_end = relocs + num_relocs;
for (rel = relocs; rel < rel_end; rel++)
{
case R_SPARC_GOT10:
case R_SPARC_GOT13:
case R_SPARC_GOT22:
+ case R_SPARC_GOTDATA_HIX22:
+ case R_SPARC_GOTDATA_LOX10:
+ case R_SPARC_GOTDATA_OP_HIX22:
+ case R_SPARC_GOTDATA_OP_LOX10:
case R_SPARC_TLS_GD_HI22:
case R_SPARC_TLS_GD_LO10:
/* This symbol requires a global offset table entry. */
case R_SPARC_GOT10:
case R_SPARC_GOT13:
case R_SPARC_GOT22:
+ case R_SPARC_GOTDATA_HIX22:
+ case R_SPARC_GOTDATA_LOX10:
+ case R_SPARC_GOTDATA_OP_HIX22:
+ case R_SPARC_GOTDATA_OP_LOX10:
tls_type = GOT_NORMAL;
break;
case R_SPARC_TLS_GD_HI22:
goto r_sparc_plt32;
break;
}
+ /* PR 7027: We need similar behaviour for 64-bit binaries. */
+ else if (r_type == R_SPARC_WPLT30)
+ break;
/* It does not make sense to have a procedure linkage
table entry for a local symbol. */
section in dynobj and make room for the reloc. */
if (sreloc == NULL)
{
- const char *name;
- bfd *dynobj;
-
- name = (bfd_elf_string_from_elf_section
- (abfd,
- elf_elfheader (abfd)->e_shstrndx,
- elf_section_data (sec)->rel_hdr.sh_name));
- if (name == NULL)
- return FALSE;
-
- BFD_ASSERT (strncmp (name, ".rela", 5) == 0
- && strcmp (bfd_get_section_name (abfd, sec),
- name + 5) == 0);
-
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
- dynobj = htab->elf.dynobj;
- sreloc = bfd_get_section_by_name (dynobj, name);
+ sreloc = _bfd_elf_make_dynamic_reloc_section
+ (sec, htab->elf.dynobj, htab->word_align_power,
+ abfd, /*rela?*/ TRUE);
+
if (sreloc == NULL)
- {
- flagword flags;
-
- flags = (SEC_HAS_CONTENTS | SEC_READONLY
- | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- if ((sec->flags & SEC_ALLOC) != 0)
- flags |= SEC_ALLOC | SEC_LOAD;
- sreloc = bfd_make_section_with_flags (dynobj,
- name,
- flags);
- if (sreloc == NULL
- || ! bfd_set_section_alignment (dynobj, sreloc,
- htab->word_align_power))
- return FALSE;
- }
- elf_section_data (sec)->sreloc = sreloc;
+ return FALSE;
}
/* If this is a global symbol, we count the number of
break;
case R_SPARC_GNU_VTENTRY:
- if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ BFD_ASSERT (h != NULL);
+ if (h != NULL
+ && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
Elf_Internal_Sym *sym)
{
if (h != NULL)
- {
- struct _bfd_sparc_elf_link_hash_table *htab;
-
- htab = _bfd_sparc_elf_hash_table (info);
- switch (SPARC_ELF_R_TYPE (rel->r_info))
+ switch (SPARC_ELF_R_TYPE (rel->r_info))
{
case R_SPARC_GNU_VTINHERIT:
case R_SPARC_GNU_VTENTRY:
- break;
-
- default:
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
-
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
-
- default:
- break;
- }
+ return NULL;
}
- }
- else
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
- return NULL;
+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
/* Update the got entry reference counts for the section being removed. */
bfd_signed_vma *local_got_refcounts;
const Elf_Internal_Rela *rel, *relend;
+ if (info->relocatable)
+ return TRUE;
+
+ BFD_ASSERT (is_sparc_elf (abfd) || sec->reloc_count == 0);
+
elf_section_data (sec)->local_dynrel = NULL;
htab = _bfd_sparc_elf_hash_table (info);
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ symtab_hdr = &elf_symtab_hdr (abfd);
sym_hashes = elf_sym_hashes (abfd);
local_got_refcounts = elf_local_got_refcounts (abfd);
case R_SPARC_GOT10:
case R_SPARC_GOT13:
case R_SPARC_GOT22:
+ case R_SPARC_GOTDATA_HIX22:
+ case R_SPARC_GOTDATA_LOX10:
+ case R_SPARC_GOTDATA_OP_HIX22:
+ case R_SPARC_GOTDATA_OP_LOX10:
if (h != NULL)
{
if (h->got.refcount > 0)
struct _bfd_sparc_elf_link_hash_entry * eh;
struct _bfd_sparc_elf_dyn_relocs *p;
asection *s;
- unsigned int power_of_two;
htab = _bfd_sparc_elf_hash_table (info);
h->needs_copy = 1;
}
- /* We need to figure out the alignment required for this symbol. I
- have no idea how ELF linkers handle this. */
- power_of_two = bfd_log2 (h->size);
- if (power_of_two > htab->align_power_max)
- power_of_two = htab->align_power_max;
-
- /* Apply the required alignment. */
s = htab->sdynbss;
- s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
- if (power_of_two > bfd_get_section_alignment (dynobj, s))
- {
- if (! bfd_set_section_alignment (dynobj, s, power_of_two))
- return FALSE;
- }
- /* Define the symbol as being at this point in the section. */
- h->root.u.def.section = s;
- h->root.u.def.value = s->size;
-
- /* Increment the section size to make room for the symbol. */
- s->size += h->size;
-
- return TRUE;
+ return _bfd_elf_adjust_dynamic_copy (h, s);
}
/* Allocate space in .plt, .got and associated reloc sections for
}
}
+ if (htab->is_vxworks)
+ {
+ struct _bfd_sparc_elf_dyn_relocs **pp;
+
+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+ {
+ if (strcmp (p->sec->output_section->name, ".tls_vars") == 0)
+ *pp = p->next;
+ else
+ pp = &p->next;
+ }
+ }
+
/* Also discard relocs on undefined weak syms with non-default
visibility. */
if (eh->dyn_relocs != NULL
Elf_Internal_Shdr *symtab_hdr;
asection *srel;
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+ if (! is_sparc_elf (ibfd))
continue;
for (s = ibfd->sections; s != NULL; s = s->next)
linker script /DISCARD/, so we'll be discarding
the relocs too. */
}
+ else if (htab->is_vxworks
+ && strcmp (p->sec->output_section->name,
+ ".tls_vars") == 0)
+ {
+ /* Relocations in vxworks .tls_vars sections are
+ handled specially by the loader. */
+ }
else if (p->count != 0)
{
srel = elf_section_data (p->sec)->sreloc;
if (!local_got)
continue;
- symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
+ symtab_hdr = &elf_symtab_hdr (ibfd);
locsymcount = symtab_hdr->sh_info;
end_local_got = local_got + locsymcount;
local_tls_type = _bfd_sparc_elf_local_got_tls_type (ibfd);
/* Strip this section if we don't need it; see the
comment below. */
}
- else if (strncmp (s->name, ".rela", 5) == 0)
+ else if (CONST_STRNEQ (s->name, ".rela"))
{
if (s->size != 0)
{
eht->dynsymcount++;
}
}
+ if (htab->is_vxworks
+ && !elf_vxworks_add_dynamic_entries (output_bfd, info))
+ return FALSE;
}
#undef add_dynamic_entry
bfd_boolean
_bfd_sparc_elf_new_section_hook (bfd *abfd, asection *sec)
{
- struct _bfd_sparc_elf_section_data *sdata;
- bfd_size_type amt = sizeof (*sdata);
+ if (!sec->used_by_bfd)
+ {
+ struct _bfd_sparc_elf_section_data *sdata;
+ bfd_size_type amt = sizeof (*sdata);
- sdata = (struct _bfd_sparc_elf_section_data *) bfd_zalloc (abfd, amt);
- if (sdata == NULL)
- return FALSE;
- sec->used_by_bfd = (PTR) sdata;
+ sdata = bfd_zalloc (abfd, amt);
+ if (sdata == NULL)
+ return FALSE;
+ sec->used_by_bfd = sdata;
+ }
return _bfd_elf_new_section_hook (abfd, sec);
}
/* Relocate a SPARC ELF section. */
bfd_boolean
-_bfd_sparc_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
- bfd *input_bfd, asection *input_section,
- bfd_byte *contents, Elf_Internal_Rela *relocs,
- Elf_Internal_Sym *local_syms, asection **local_sections)
+_bfd_sparc_elf_relocate_section (bfd *output_bfd,
+ struct bfd_link_info *info,
+ bfd *input_bfd,
+ asection *input_section,
+ bfd_byte *contents,
+ Elf_Internal_Rela *relocs,
+ Elf_Internal_Sym *local_syms,
+ asection **local_sections)
{
struct _bfd_sparc_elf_link_hash_table *htab;
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
int num_relocs;
-
- if (info->relocatable)
- return TRUE;
+ bfd_boolean is_vxworks_tls;
htab = _bfd_sparc_elf_hash_table (info);
- symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ symtab_hdr = &elf_symtab_hdr (input_bfd);
sym_hashes = elf_sym_hashes (input_bfd);
local_got_offsets = elf_local_got_offsets (input_bfd);
got_base = elf_hash_table (info)->hgot->root.u.def.value;
sreloc = elf_section_data (input_section)->sreloc;
+ /* We have to handle relocations in vxworks .tls_vars sections
+ specially, because the dynamic loader is 'weird'. */
+ is_vxworks_tls = (htab->is_vxworks && info->shared
+ && !strcmp (input_section->output_section->name,
+ ".tls_vars"));
rel = relocs;
if (ABI_64_P (output_bfd))
}
howto = _bfd_sparc_elf_howto_table + r_type;
- /* This is a final link. */
r_symndx = SPARC_ELF_R_SYMNDX (htab, rel->r_info);
h = NULL;
sym = NULL;
}
}
+ if (sec != NULL && elf_discarded_section (sec))
+ {
+ /* For relocs against symbols from removed linkonce
+ sections, or sections discarded by a linker script, we
+ just want the section contents zeroed. Avoid any
+ special processing. */
+ _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
+ rel->r_info = 0;
+ rel->r_addend = 0;
+ continue;
+ }
+
+ if (info->relocatable)
+ continue;
+
switch (r_type)
{
+ case R_SPARC_GOTDATA_HIX22:
+ case R_SPARC_GOTDATA_LOX10:
+ case R_SPARC_GOTDATA_OP_HIX22:
+ case R_SPARC_GOTDATA_OP_LOX10:
+ /* We don't support these code transformation optimizations
+ yet, so just leave the sequence alone and treat as
+ GOT22/GOT10. */
+ if (r_type == R_SPARC_GOTDATA_HIX22
+ || r_type == R_SPARC_GOTDATA_OP_HIX22)
+ r_type = R_SPARC_GOT22;
+ else
+ r_type = R_SPARC_GOT10;
+ /* Fall through. */
+
case R_SPARC_GOT10:
case R_SPARC_GOT13:
case R_SPARC_GOT22:
0, R_SPARC_RELATIVE);
outrel.r_addend = relocation;
relocation = 0;
- SPARC_ELF_APPEND_RELA (htab, output_bfd, s, &outrel);
+ sparc_elf_append_rela (output_bfd, s, &outrel);
}
SPARC_ELF_PUT_WORD (htab, output_bfd, relocation,
if (h == NULL)
break;
}
+ /* PR 7027: We need similar behaviour for 64-bit binaries. */
+ else if (r_type == R_SPARC_WPLT30 && h == NULL)
+ break;
else
{
BFD_ASSERT (h != NULL);
case R_SPARC_L44:
case R_SPARC_UA64:
r_sparc_plt32:
- /* r_symndx will be zero only for relocs against symbols
- from removed linkonce sections, or sections discarded by
- a linker script. */
- if (r_symndx == 0
- || (input_section->flags & SEC_ALLOC) == 0)
+ if ((input_section->flags & SEC_ALLOC) == 0
+ || is_vxworks_tls)
break;
if ((info->shared
{
long indx;
+ outrel.r_addend = relocation + rel->r_addend;
+
if (is_plt)
sec = htab->splt;
{
asection *osec;
+ /* We are turning this relocation into one
+ against a section symbol. It would be
+ proper to subtract the symbol's value,
+ osec->vma, from the emitted reloc addend,
+ but ld.so expects buggy relocs. */
osec = sec->output_section;
indx = elf_section_data (osec)->dynindx;
+ if (indx == 0)
+ {
+ osec = htab->elf.text_index_section;
+ indx = elf_section_data (osec)->dynindx;
+ }
+
/* FIXME: we really should be able to link non-pic
shared libraries. */
if (indx == 0)
}
}
- outrel.r_info = SPARC_ELF_R_INFO (htab, rel, indx, r_type);
- outrel.r_addend = relocation + rel->r_addend;
+ outrel.r_info = SPARC_ELF_R_INFO (htab, rel, indx,
+ r_type);
}
}
- SPARC_ELF_APPEND_RELA (htab, output_bfd, sreloc, &outrel);
+ sparc_elf_append_rela (output_bfd, sreloc, &outrel);
/* This reloc will be computed at runtime, so there's no
need to do anything now. */
else
outrel.r_addend = 0;
outrel.r_info = SPARC_ELF_R_INFO (htab, NULL, indx, dr_type);
- SPARC_ELF_APPEND_RELA (htab, output_bfd, htab->srelgot, &outrel);
+ sparc_elf_append_rela (output_bfd, htab->srelgot, &outrel);
if (r_type == R_SPARC_TLS_GD_HI22
|| r_type == R_SPARC_TLS_GD_LO10)
outrel.r_info = SPARC_ELF_R_INFO (htab, NULL, indx,
SPARC_ELF_DTPOFF_RELOC (htab));
outrel.r_offset += SPARC_ELF_WORD_BYTES (htab);
- SPARC_ELF_APPEND_RELA (htab, output_bfd, htab->srelgot, &outrel);
+ sparc_elf_append_rela (output_bfd, htab->srelgot,
+ &outrel);
}
}
else if (dr_type == SPARC_ELF_DTPMOD_RELOC (htab))
+ rel->r_addend;
}
- SPARC_ELF_APPEND_RELA (htab, output_bfd, sreloc, &outrel);
+ sparc_elf_append_rela (output_bfd, sreloc, &outrel);
continue;
}
relocation = tpoff (info, relocation);
}
continue;
+ case R_SPARC_GOTDATA_OP:
+ /* We don't support gotdata code transformation optimizations
+ yet, so simply leave the sequence as-is. */
+ continue;
+
case R_SPARC_TLS_IE_LD:
case R_SPARC_TLS_IE_LDX:
if (! info->shared && (h == NULL || h->dynindx == -1))
{
bfd *dynobj;
struct _bfd_sparc_elf_link_hash_table *htab;
+ const struct elf_backend_data *bed;
htab = _bfd_sparc_elf_hash_table (info);
dynobj = htab->elf.dynobj;
+ bed = get_elf_backend_data (output_bfd);
if (h->plt.offset != (bfd_vma) -1)
{
thus .plt[4] has corresponding .rela.plt[0] and so on. */
loc = srela->contents;
-#ifdef BFD64
- if (ABI_64_P (output_bfd))
- {
- loc += rela_index * sizeof (Elf64_External_Rela);
- bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
- }
- else
-#endif
- {
- loc += rela_index * sizeof (Elf32_External_Rela);
- bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
- }
+ loc += rela_index * bed->s->sizeof_rela;
+ bed->s->swap_reloca_out (output_bfd, &rela, loc);
if (!h->def_regular)
{
SPARC_ELF_PUT_WORD (htab, output_bfd, 0,
sgot->contents + (h->got.offset & ~(bfd_vma) 1));
- SPARC_ELF_APPEND_RELA (htab, output_bfd, srela, &rela);
+ sparc_elf_append_rela (output_bfd, srela, &rela);
}
if (h->needs_copy)
+ h->root.u.def.section->output_offset);
rela.r_info = SPARC_ELF_R_INFO (htab, NULL, h->dynindx, R_SPARC_COPY);
rela.r_addend = 0;
- SPARC_ELF_APPEND_RELA (htab, output_bfd, s, &rela);
+ sparc_elf_append_rela (output_bfd, s, &rela);
}
/* Mark some specially defined symbols as absolute. On VxWorks,
/* Finish up the dynamic sections. */
-#ifdef BFD64
-static bfd_boolean
-sparc64_finish_dyn (bfd *output_bfd, struct bfd_link_info *info,
- bfd *dynobj, asection *sdyn,
- asection *splt ATTRIBUTE_UNUSED)
-{
- Elf64_External_Dyn *dyncon, *dynconend;
- int stt_regidx = -1;
-
- dyncon = (Elf64_External_Dyn *) sdyn->contents;
- dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size);
- for (; dyncon < dynconend; dyncon++)
- {
- Elf_Internal_Dyn dyn;
- const char *name;
- bfd_boolean size;
-
- bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
-
- switch (dyn.d_tag)
- {
- case DT_PLTGOT: name = ".plt"; size = FALSE; break;
- case DT_PLTRELSZ: name = ".rela.plt"; size = TRUE; break;
- case DT_JMPREL: name = ".rela.plt"; size = FALSE; break;
- case DT_SPARC_REGISTER:
- if (stt_regidx == -1)
- {
- stt_regidx =
- _bfd_elf_link_lookup_local_dynindx (info, output_bfd, -1);
- if (stt_regidx == -1)
- return FALSE;
- }
- dyn.d_un.d_val = stt_regidx++;
- bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
- /* fallthrough */
- default: name = NULL; size = FALSE; break;
- }
-
- if (name != NULL)
- {
- asection *s;
-
- s = bfd_get_section_by_name (output_bfd, name);
- if (s == NULL)
- dyn.d_un.d_val = 0;
- else
- {
- if (! size)
- dyn.d_un.d_ptr = s->vma;
- else
- dyn.d_un.d_val = s->size;
- }
- bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
- }
- }
- return TRUE;
-}
-#endif
-
static bfd_boolean
-sparc32_finish_dyn (bfd *output_bfd, struct bfd_link_info *info,
- bfd *dynobj, asection *sdyn,
- asection *splt ATTRIBUTE_UNUSED)
+sparc_finish_dyn (bfd *output_bfd, struct bfd_link_info *info,
+ bfd *dynobj, asection *sdyn,
+ asection *splt ATTRIBUTE_UNUSED)
{
- Elf32_External_Dyn *dyncon, *dynconend;
struct _bfd_sparc_elf_link_hash_table *htab;
+ const struct elf_backend_data *bed;
+ bfd_byte *dyncon, *dynconend;
+ size_t dynsize;
+ int stt_regidx = -1;
+ bfd_boolean abi_64_p;
htab = _bfd_sparc_elf_hash_table (info);
- dyncon = (Elf32_External_Dyn *) sdyn->contents;
- dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
- for (; dyncon < dynconend; dyncon++)
+ bed = get_elf_backend_data (output_bfd);
+ dynsize = bed->s->sizeof_dyn;
+ dynconend = sdyn->contents + sdyn->size;
+ abi_64_p = ABI_64_P (output_bfd);
+ for (dyncon = sdyn->contents; dyncon < dynconend; dyncon += dynsize)
{
Elf_Internal_Dyn dyn;
const char *name;
bfd_boolean size;
- bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
+ bed->s->swap_dyn_in (dynobj, dyncon, &dyn);
if (htab->is_vxworks && dyn.d_tag == DT_RELASZ)
{
if (htab->srelplt)
{
dyn.d_un.d_val -= htab->srelplt->size;
- bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ bed->s->swap_dyn_out (output_bfd, &dyn, dyncon);
}
}
else if (htab->is_vxworks && dyn.d_tag == DT_PLTGOT)
{
dyn.d_un.d_val = (htab->sgotplt->output_section->vma
+ htab->sgotplt->output_offset);
- bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ bed->s->swap_dyn_out (output_bfd, &dyn, dyncon);
+ }
+ }
+ else if (htab->is_vxworks
+ && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
+ bed->s->swap_dyn_out (output_bfd, &dyn, dyncon);
+ else if (abi_64_p && dyn.d_tag == DT_SPARC_REGISTER)
+ {
+ if (stt_regidx == -1)
+ {
+ stt_regidx =
+ _bfd_elf_link_lookup_local_dynindx (info, output_bfd, -1);
+ if (stt_regidx == -1)
+ return FALSE;
}
+ dyn.d_un.d_val = stt_regidx++;
+ bed->s->swap_dyn_out (output_bfd, &dyn, dyncon);
}
else
{
case DT_PLTGOT: name = ".plt"; size = FALSE; break;
case DT_PLTRELSZ: name = ".rela.plt"; size = TRUE; break;
case DT_JMPREL: name = ".rela.plt"; size = FALSE; break;
- default: name = NULL; size = FALSE; break;
+ default: name = NULL; size = FALSE; break;
}
if (name != NULL)
else
dyn.d_un.d_val = s->size;
}
- bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ bed->s->swap_dyn_out (output_bfd, &dyn, dyncon);
}
}
}
if (elf_hash_table (info)->dynamic_sections_created)
{
asection *splt;
- bfd_boolean ret;
splt = bfd_get_section_by_name (dynobj, ".plt");
BFD_ASSERT (splt != NULL && sdyn != NULL);
-#ifdef BFD64
- if (ABI_64_P (output_bfd))
- ret = sparc64_finish_dyn (output_bfd, info, dynobj, sdyn, splt);
- else
-#endif
- ret = sparc32_finish_dyn (output_bfd, info, dynobj, sdyn, splt);
-
- if (ret != TRUE)
- return ret;
+ if (!sparc_finish_dyn (output_bfd, info, dynobj, sdyn, splt))
+ return FALSE;
/* Initialize the contents of the .plt section. */
if (splt->size > 0)
}
elf_section_data (splt->output_section)->this_hdr.sh_entsize
- = htab->plt_entry_size;
+ = (htab->is_vxworks || !ABI_64_P (output_bfd))
+ ? 0 : htab->plt_entry_size;
}
/* Set the first entry in the global offset table to the address of