/* IBM S/390-specific support for 32-bit ELF
- Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Contributed by Carl B. Pedersen and Martin Schwidefsky.
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,
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"
#define elf_s390_hash_entry(ent) \
((struct elf_s390_link_hash_entry *)(ent))
+/* NOTE: Keep this structure in sync with
+ the one declared in elf64-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_TDATA)
+
static bfd_boolean
elf_s390_mkobject (bfd *abfd)
{
- if (abfd->tdata.any == NULL)
- {
- 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 bfd_elf_mkobject (abfd);
+ return bfd_elf_allocate_object (abfd, sizeof (struct elf_s390_obj_tdata),
+ S390_ELF_TDATA);
}
static bfd_boolean
if (info->relocatable)
return TRUE;
+ BFD_ASSERT (is_s390_elf (abfd));
+
htab = elf_s390_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);
&& ELF32_R_TYPE (rel->r_info) != R_390_PC32DBL
&& ELF32_R_TYPE (rel->r_info) != R_390_PC32)
|| (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 (! CONST_STRNEQ (name, ".rela")
- || 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, 2, 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, 2))
- return FALSE;
- }
- elf_section_data (sec)->sreloc = sreloc;
+ return FALSE;
}
/* If this is a global symbol, we count the number of
/* 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;
bfd_signed_vma *local_got_refcounts;
const Elf_Internal_Rela *rel, *relend;
+ if (info->relocatable)
+ return TRUE;
+
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_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
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
htab = elf_s390_hash_table (info);
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;
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)
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);
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
+ BFD_ASSERT (is_s390_elf (input_bfd));
+
htab = elf_s390_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);
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))
{
&& r_type != R_390_PC16DBL
&& r_type != R_390_PC32DBL
&& r_type != R_390_PC32)
- || (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_PC32
|| !info->shared
- || !info->symbolic
+ || !SYMBOLIC_BIND (info, h)
|| !h->def_regular))
{
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
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 = ELF32_R_INFO (0, R_390_RELATIVE);
rela.r_addend = (h->root.u.def.value