/* IBM S/390-specific support for 64-bit ELF
- Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+ 2010, 2011, 2012 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., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
static bfd_boolean elf_s390_create_dynamic_sections
PARAMS((bfd *, struct bfd_link_info *));
static void elf_s390_copy_indirect_symbol
- PARAMS ((const struct elf_backend_data *, struct elf_link_hash_entry *,
+ PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *,
struct elf_link_hash_entry *));
static bfd_boolean elf_s390_check_relocs
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
-static asection *elf_s390_gc_mark_hook
- PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
- struct elf_link_hash_entry *, Elf_Internal_Sym *));
-static bfd_boolean elf_s390_gc_sweep_hook
- PARAMS ((bfd *, struct bfd_link_info *, asection *,
- const Elf_Internal_Rela *));
struct elf_s390_link_hash_entry;
static void elf_s390_adjust_gotplt
PARAMS ((struct elf_s390_link_hash_entry *));
PARAMS ((const Elf_Internal_Rela *));
static bfd_boolean elf_s390_finish_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
-static bfd_boolean elf_s390_mkobject
- PARAMS ((bfd *));
static bfd_boolean elf_s390_object_p
PARAMS ((bfd *));
static int elf_s390_tls_transition
return 0;
}
+static reloc_howto_type *
+elf_s390_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]);
+ i++)
+ if (elf_howto_table[i].name != NULL
+ && strcasecmp (elf_howto_table[i].name, r_name) == 0)
+ return &elf_howto_table[i];
+
+ if (strcasecmp (elf64_s390_vtinherit_howto.name, r_name) == 0)
+ return &elf64_s390_vtinherit_howto;
+ if (strcasecmp (elf64_s390_vtentry_howto.name, r_name) == 0)
+ return &elf64_s390_vtentry_howto;
+
+ return NULL;
+}
+
/* We need to use ELF64_R_TYPE so we have our own copy of this function,
and elf64-s390.c has its own copy. */
arelent *cache_ptr;
Elf_Internal_Rela *dst;
{
- switch (ELF64_R_TYPE(dst->r_info))
+ unsigned int r_type = ELF64_R_TYPE(dst->r_info);
+ switch (r_type)
{
case R_390_GNU_VTINHERIT:
cache_ptr->howto = &elf64_s390_vtinherit_howto;
break;
default:
- BFD_ASSERT (ELF64_R_TYPE(dst->r_info) < (unsigned int) R_390_max);
- cache_ptr->howto = &elf_howto_table[ELF64_R_TYPE(dst->r_info)];
+ if (r_type >= sizeof (elf_howto_table) / sizeof (elf_howto_table[0]))
+ {
+ (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
+ abfd, (int) r_type);
+ r_type = R_390_NONE;
+ }
+ cache_ptr->howto = &elf_howto_table[r_type];
}
}
#define elf_s390_hash_entry(ent) \
((struct elf_s390_link_hash_entry *)(ent))
+/* NOTE: Keep this structure in sync with
+ the one declared in elf32-s390.c. */
struct elf_s390_obj_tdata
{
struct elf_obj_tdata root;
- /* tls_type for each local got entry. */
+ /* TLS type for each local got entry. */
char *local_got_tls_type;
};
#define elf_s390_local_got_tls_type(abfd) \
(elf_s390_tdata (abfd)->local_got_tls_type)
+#define is_s390_elf(bfd) \
+ (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
+ && elf_tdata (bfd) != NULL \
+ && elf_object_id (bfd) == S390_ELF_DATA)
+
static bfd_boolean
-elf_s390_mkobject (abfd)
- bfd *abfd;
+elf_s390_mkobject (bfd *abfd)
{
- bfd_size_type amt = sizeof (struct elf_s390_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 elf_s390_obj_tdata),
+ S390_ELF_DATA);
}
static bfd_boolean
bfd_vma offset;
} tls_ldm_got;
- /* Small local sym to section mapping cache. */
- struct sym_sec_cache sym_sec;
+ /* Small local sym cache. */
+ struct sym_cache sym_cache;
};
/* Get the s390 ELF linker hash table from a link_info structure. */
#define elf_s390_hash_table(p) \
- ((struct elf_s390_link_hash_table *) ((p)->hash))
+ (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
+ == S390_ELF_DATA ? ((struct elf_s390_link_hash_table *) ((p)->hash)) : NULL)
/* Create an entry in an s390 ELF linker hash table. */
if (ret == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
+ sizeof (struct elf_s390_link_hash_entry),
+ S390_ELF_DATA))
{
free (ret);
return NULL;
ret->sdynbss = NULL;
ret->srelbss = NULL;
ret->tls_ldm_got.refcount = 0;
- ret->sym_sec.abfd = NULL;
+ ret->sym_cache.abfd = NULL;
return &ret->elf.root;
}
shortcuts to them in our hash table. */
static bfd_boolean
-create_got_section (dynobj, info)
- bfd *dynobj;
- struct bfd_link_info *info;
+create_got_section (bfd *dynobj,
+ struct bfd_link_info *info)
{
struct elf_s390_link_hash_table *htab;
return FALSE;
htab = elf_s390_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
htab->sgot = bfd_get_section_by_name (dynobj, ".got");
htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
- if (!htab->sgot || !htab->sgotplt)
+ htab->srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ if (!htab->sgot || !htab->sgotplt || !htab->srelgot)
abort ();
-
- htab->srelgot = bfd_make_section (dynobj, ".rela.got");
- if (htab->srelgot == NULL
- || ! bfd_set_section_flags (dynobj, htab->srelgot,
- (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY | SEC_LINKER_CREATED
- | SEC_READONLY))
- || ! bfd_set_section_alignment (dynobj, htab->srelgot, 3))
- return FALSE;
return TRUE;
}
hash table. */
static bfd_boolean
-elf_s390_create_dynamic_sections (dynobj, info)
- bfd *dynobj;
- struct bfd_link_info *info;
+elf_s390_create_dynamic_sections (bfd *dynobj,
+ struct bfd_link_info *info)
{
struct elf_s390_link_hash_table *htab;
htab = elf_s390_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
if (!htab->sgot && !create_got_section (dynobj, info))
return FALSE;
/* Copy the extra info we tack onto an elf_link_hash_entry. */
static void
-elf_s390_copy_indirect_symbol (bed, dir, ind)
- const struct elf_backend_data *bed;
+elf_s390_copy_indirect_symbol (info, dir, ind)
+ struct bfd_link_info *info;
struct elf_link_hash_entry *dir, *ind;
{
struct elf_s390_link_hash_entry *edir, *eind;
struct elf_s390_dyn_relocs **pp;
struct elf_s390_dyn_relocs *p;
- if (ind->root.type == bfd_link_hash_indirect)
- abort ();
-
- /* Add reloc counts against the weak sym to the strong sym
+ /* Add reloc counts against the indirect sym to the direct sym
list. Merge any entries against the same section. */
for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
{
dir->needs_plt |= ind->needs_plt;
}
else
- _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
+ _bfd_elf_link_hash_copy_indirect (info, dir, ind);
}
static int
table. */
static bfd_boolean
-elf_s390_check_relocs (abfd, info, sec, relocs)
- bfd *abfd;
- struct bfd_link_info *info;
- asection *sec;
- const Elf_Internal_Rela *relocs;
+elf_s390_check_relocs (bfd *abfd,
+ struct bfd_link_info *info,
+ asection *sec,
+ const Elf_Internal_Rela *relocs)
{
struct elf_s390_link_hash_table *htab;
Elf_Internal_Shdr *symtab_hdr;
if (info->relocatable)
return TRUE;
+ BFD_ASSERT (is_s390_elf (abfd));
+
htab = elf_s390_hash_table (info);
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ if (htab == NULL)
+ return FALSE;
+
+ symtab_hdr = &elf_symtab_hdr (abfd);
sym_hashes = elf_sym_hashes (abfd);
local_got_refcounts = elf_local_got_refcounts (abfd);
if (r_symndx < symtab_hdr->sh_info)
h = NULL;
else
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ 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;
+ }
/* Create got section and local_got_refcounts array if they
are needed. */
&& ELF64_R_TYPE (rel->r_info) != R_390_PC32DBL
&& ELF64_R_TYPE (rel->r_info) != R_390_PC64)
|| (h != NULL
- && (! info->symbolic
+ && (! SYMBOLIC_BIND (info, h)
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
|| (ELIMINATE_COPY_RELOCS
this 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;
-
- if (strncmp (name, ".rela", 5) != 0
- || strcmp (bfd_get_section_name (abfd, sec),
- name + 5) != 0)
- {
- (*_bfd_error_handler)
- (_("%B: bad relocation section name `%s\'"),
- abfd, name);
- }
-
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, 3, abfd, /*rela?*/ TRUE);
+
if (sreloc == NULL)
- {
- flagword flags;
-
- sreloc = bfd_make_section (dynobj, name);
- flags = (SEC_HAS_CONTENTS | SEC_READONLY
- | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- if ((sec->flags & SEC_ALLOC) != 0)
- flags |= SEC_ALLOC | SEC_LOAD;
- if (sreloc == NULL
- || ! bfd_set_section_flags (dynobj, sreloc, flags)
- || ! bfd_set_section_alignment (dynobj, sreloc, 3))
- return FALSE;
- }
- elf_section_data (sec)->sreloc = sreloc;
+ return FALSE;
}
/* If this is a global symbol, we count the number of
/* Track dynamic relocs needed for local syms too.
We really need local syms available to do this
easily. Oh well. */
-
asection *s;
- s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
- sec, r_symndx);
- if (s == NULL)
+ void *vpp;
+ Elf_Internal_Sym *isym;
+
+ isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+ abfd, r_symndx);
+ if (isym == NULL)
return FALSE;
- head = ((struct elf_s390_dyn_relocs **)
- &elf_section_data (s)->local_dynrel);
+ s = bfd_section_from_elf_index (abfd, isym->st_shndx);
+ if (s == NULL)
+ s = sec;
+
+ vpp = &elf_section_data (s)->local_dynrel;
+ head = (struct elf_s390_dyn_relocs **) vpp;
}
p = *head;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_390_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;
relocation. */
static asection *
-elf_s390_gc_mark_hook (sec, info, rel, h, sym)
- asection *sec;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- Elf_Internal_Rela *rel;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
+elf_s390_gc_mark_hook (asection *sec,
+ struct bfd_link_info *info,
+ Elf_Internal_Rela *rel,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym)
{
if (h != NULL)
- {
- switch (ELF64_R_TYPE (rel->r_info))
- {
- case R_390_GNU_VTINHERIT:
- case R_390_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;
- }
- }
- }
- else
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-
- return NULL;
+ switch (ELF64_R_TYPE (rel->r_info))
+ {
+ case R_390_GNU_VTINHERIT:
+ case R_390_GNU_VTENTRY:
+ return NULL;
+ }
+
+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
/* Update the got entry reference counts for the section being removed. */
static bfd_boolean
-elf_s390_gc_sweep_hook (abfd, info, sec, relocs)
- bfd *abfd;
- struct bfd_link_info *info;
- asection *sec;
- const Elf_Internal_Rela *relocs;
+elf_s390_gc_sweep_hook (bfd *abfd,
+ struct bfd_link_info *info,
+ asection *sec,
+ const Elf_Internal_Rela *relocs)
{
+ struct elf_s390_link_hash_table *htab;
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
bfd_signed_vma *local_got_refcounts;
const Elf_Internal_Rela *rel, *relend;
+ if (info->relocatable)
+ return TRUE;
+
+ htab = elf_s390_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
elf_section_data (sec)->local_dynrel = NULL;
- 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);
struct elf_s390_dyn_relocs *p;
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ 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;
eh = (struct elf_s390_link_hash_entry *) h;
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
switch (r_type)
{
case R_390_TLS_LDM64:
- if (elf_s390_hash_table (info)->tls_ldm_got.refcount > 0)
- elf_s390_hash_table (info)->tls_ldm_got.refcount -= 1;
+ if (htab->tls_ldm_got.refcount > 0)
+ htab->tls_ldm_got.refcount -= 1;
break;
case R_390_TLS_GD64:
understand. */
static bfd_boolean
-elf_s390_adjust_dynamic_symbol (info, h)
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
+elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
{
struct elf_s390_link_hash_table *htab;
asection *s;
- unsigned int power_of_two;
/* If this is a function, put it in the procedure linkage table. We
will fill in the contents of the procedure linkage table later
|| h->needs_plt)
{
if (h->plt.refcount <= 0
- || (! info->shared
- && !h->def_dynamic
- && !h->ref_dynamic
- && h->root.type != bfd_link_hash_undefweak
- && h->root.type != bfd_link_hash_undefined))
+ || SYMBOL_CALLS_LOCAL (info, h)
+ || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ && h->root.type == bfd_link_hash_undefweak))
{
/* This case can occur if we saw a PLT32 reloc in an input
file, but the symbol was never referred to by a dynamic
same memory location for the variable. */
htab = elf_s390_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
/* We must generate a R_390_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
- 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 += sizeof (Elf64_External_Rela);
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 > 3)
- power_of_two = 3;
-
- /* 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 (htab->elf.dynobj, s))
- {
- if (! bfd_set_section_alignment (htab->elf.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
dynamic relocs. */
static bfd_boolean
-allocate_dynrelocs (h, inf)
- struct elf_link_hash_entry *h;
- PTR inf;
+allocate_dynrelocs (struct elf_link_hash_entry *h,
+ void * inf)
{
struct bfd_link_info *info;
struct elf_s390_link_hash_table *htab;
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
- if (h->root.type == bfd_link_hash_warning)
- /* When warning symbols are created, they **replace** the "real"
- entry in the hash table, thus we never get to see the real
- symbol in a hash traversal. So look at it now. */
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
info = (struct bfd_link_info *) inf;
htab = elf_s390_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
if (htab->elf.dynamic_sections_created
- && h->plt.refcount > 0
- && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
- || h->root.type != bfd_link_hash_undefweak))
+ && h->plt.refcount > 0)
{
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
if (info->shared)
{
- if (SYMBOL_REFERENCES_LOCAL (info, h))
+ if (SYMBOL_CALLS_LOCAL (info, h))
{
struct elf_s390_dyn_relocs **pp;
/* Also discard relocs on undefined weak syms with non-default
visibility. */
- if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ if (eh->dyn_relocs != NULL
&& h->root.type == bfd_link_hash_undefweak)
- eh->dyn_relocs = NULL;
+ {
+ if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+ eh->dyn_relocs = NULL;
+
+ /* Make sure undefined weak symbols are output as a dynamic
+ symbol in PIEs. */
+ else if (h->dynindx == -1
+ && !h->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+ }
}
else if (ELIMINATE_COPY_RELOCS)
{
struct elf_s390_link_hash_entry *eh;
struct elf_s390_dyn_relocs *p;
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
eh = (struct elf_s390_link_hash_entry *) h;
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
/* Set the sizes of the dynamic sections. */
static bfd_boolean
-elf_s390_size_dynamic_sections (output_bfd, info)
- bfd *output_bfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info;
+elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info)
{
struct elf_s390_link_hash_table *htab;
bfd *dynobj;
bfd *ibfd;
htab = elf_s390_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
dynobj = htab->elf.dynobj;
if (dynobj == NULL)
abort ();
Elf_Internal_Shdr *symtab_hdr;
asection *srela;
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+ if (! is_s390_elf (ibfd))
continue;
for (s = ibfd->sections; s != NULL; s = s->next)
{
struct elf_s390_dyn_relocs *p;
- for (p = *((struct elf_s390_dyn_relocs **)
- &elf_section_data (s)->local_dynrel);
- p != NULL;
- p = p->next)
+ for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
{
if (!bfd_is_abs_section (p->sec)
&& bfd_is_abs_section (p->sec->output_section))
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 = elf_s390_local_got_tls_type (ibfd);
if (s == htab->splt
|| s == htab->sgot
- || s == htab->sgotplt)
+ || s == htab->sgotplt
+ || s == htab->sdynbss)
{
/* Strip this section if we don't need it; see the
comment below. */
}
- else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
+ else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela"))
{
if (s->size != 0 && s != htab->srelplt)
relocs = TRUE;
function which decides whether anything needs to go
into these sections. */
- _bfd_strip_section_from_output (info, s);
+ s->flags |= SEC_EXCLUDE;
continue;
}
+ if ((s->flags & SEC_HAS_CONTENTS) == 0)
+ continue;
+
/* Allocate memory for the section contents. We use bfd_zalloc
here in case unused entries are not reclaimed before the
section's contents are written out. This should not happen,
input_section,
(long) rel->r_offset,
howto->name);
+ bfd_set_error (bfd_error_bad_value);
}
/* Relocate a 390 ELF section. */
static bfd_boolean
-elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
- contents, relocs, local_syms, local_sections)
- 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;
+elf_s390_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 elf_s390_link_hash_table *htab;
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
- if (info->relocatable)
- return TRUE;
+ BFD_ASSERT (is_s390_elf (input_bfd));
htab = elf_s390_hash_table (info);
- symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ if (htab == NULL)
+ return FALSE;
+
+ symtab_hdr = &elf_symtab_hdr (input_bfd);
sym_hashes = elf_sym_hashes (input_bfd);
local_got_offsets = elf_local_got_offsets (input_bfd);
howto = elf_howto_table + r_type;
r_symndx = ELF64_R_SYM (rel->r_info);
- /* This is a final link. */
h = NULL;
sym = NULL;
sec = NULL;
unresolved_reloc, warned);
}
+ if (sec != NULL && elf_discarded_section (sec))
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, relend, howto, contents);
+
+ if (info->relocatable)
+ continue;
+
switch (r_type)
{
case R_390_GOTPLT12:
dyn = htab->elf.dynamic_sections_created;
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
|| (info->shared
- && (info->symbolic
- || h->dynindx == -1
- || h->forced_local)
- && h->def_regular)
+ && SYMBOL_REFERENCES_LOCAL (info, h))
|| (ELF_ST_VISIBILITY (h->other)
&& h->root.type == bfd_link_hash_undefweak))
{
case R_390_PC32:
case R_390_PC32DBL:
case R_390_PC64:
- /* 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)
break;
if ((info->shared
&& r_type != R_390_PC32
&& r_type != R_390_PC32DBL
&& r_type != R_390_PC64)
- || (h != NULL
- && !SYMBOL_REFERENCES_LOCAL (info, h))))
+ || !SYMBOL_CALLS_LOCAL (info, h)))
|| (ELIMINATE_COPY_RELOCS
&& !info->shared
&& h != NULL
|| r_type == R_390_PC32DBL
|| r_type == R_390_PC64
|| !info->shared
- || !info->symbolic
+ || !SYMBOLIC_BIND (info, h)
|| !h->def_regular))
{
outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
osec = sec->output_section;
sindx = elf_section_data (osec)->dynindx;
- BFD_ASSERT (sindx > 0);
+
+ if (sindx == 0)
+ {
+ osec = htab->elf.text_index_section;
+ sindx = elf_section_data (osec)->dynindx;
+ }
+ BFD_ASSERT (sindx != 0);
/* We are turning this relocation into one
against a section symbol, so subtract out
the output section's address but not the
offset of the input section in the output
section. */
-
outrel.r_addend -= osec->vma;
}
outrel.r_info = ELF64_R_INFO (sindx, r_type);
continue;
case R_390_TLS_LDO64:
- if (info->shared || (input_section->flags & SEC_CODE) == 0)
+ if (info->shared || (input_section->flags & SEC_DEBUGGING))
relocation -= dtpoff_base (info);
else
/* When converting LDO to LE, we must negate. */
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 relocation against symbol `%s'"),
+ (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
input_bfd,
input_section,
(long) rel->r_offset,
+ howto->name,
h->root.root.string);
if (r_type == R_390_20
dynamic sections here. */
static bfd_boolean
-elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym)
- bfd *output_bfd;
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
+elf_s390_finish_dynamic_symbol (bfd *output_bfd,
+ struct bfd_link_info *info,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym)
{
struct elf_s390_link_hash_table *htab;
htab = elf_s390_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
if (h->plt.offset != (bfd_vma) -1)
{
The entry in the global offset table will already have been
initialized in the relocate_section function. */
if (info->shared
- && (info->symbolic
- || h->dynindx == -1
- || h->forced_local)
- && h->def_regular)
+ && SYMBOL_REFERENCES_LOCAL (info, h))
{
+ if (!h->def_regular)
+ return FALSE;
BFD_ASSERT((h->got.offset & 1) != 0);
rela.r_info = ELF64_R_INFO (0, R_390_RELATIVE);
rela.r_addend = (h->root.u.def.value
/* Mark some specially defined symbols as absolute. */
if (strcmp (h->root.root.string, "_DYNAMIC") == 0
- || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
- || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
+ || h == htab->elf.hgot
+ || h == htab->elf.hplt)
sym->st_shndx = SHN_ABS;
return TRUE;
/* Finish up the dynamic sections. */
static bfd_boolean
-elf_s390_finish_dynamic_sections (output_bfd, info)
- bfd *output_bfd;
- struct bfd_link_info *info;
+elf_s390_finish_dynamic_sections (bfd *output_bfd,
+ struct bfd_link_info *info)
{
struct elf_s390_link_hash_table *htab;
bfd *dynobj;
asection *sdyn;
htab = elf_s390_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
dynobj = htab->elf.dynobj;
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
ELFCLASS64, EV_CURRENT,
bfd_elf64_write_out_phdrs,
bfd_elf64_write_shdrs_and_ehdr,
+ bfd_elf64_checksum_contents,
bfd_elf64_write_relocs,
bfd_elf64_swap_symbol_in,
bfd_elf64_swap_symbol_out,
#define TARGET_BIG_SYM bfd_elf64_s390_vec
#define TARGET_BIG_NAME "elf64-s390"
#define ELF_ARCH bfd_arch_s390
+#define ELF_TARGET_ID S390_ELF_DATA
#define ELF_MACHINE_CODE EM_S390
#define ELF_MACHINE_ALT1 EM_S390_OLD
#define ELF_MAXPAGESIZE 0x1000
#define bfd_elf64_bfd_is_local_label_name elf_s390_is_local_label_name
#define bfd_elf64_bfd_link_hash_table_create elf_s390_link_hash_table_create
#define bfd_elf64_bfd_reloc_type_lookup elf_s390_reloc_type_lookup
+#define bfd_elf64_bfd_reloc_name_lookup elf_s390_reloc_name_lookup
#define elf_backend_adjust_dynamic_symbol elf_s390_adjust_dynamic_symbol
#define elf_backend_check_relocs elf_s390_check_relocs
#define elf_backend_reloc_type_class elf_s390_reloc_type_class
#define elf_backend_relocate_section elf_s390_relocate_section
#define elf_backend_size_dynamic_sections elf_s390_size_dynamic_sections
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_reloc_type_class elf_s390_reloc_type_class
#define elf_backend_plt_sym_val elf_s390_plt_sym_val