/* 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, 2009
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,
#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_DATA)
+
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_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. */
return NULL;
if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
- sizeof (struct elf_s390_link_hash_entry)))
+ 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;
}
htab = elf_s390_hash_table (info);
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_with_flags (dynobj, ".rela.got",
- (SEC_ALLOC | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY));
- if (htab->srelgot == NULL
- || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
- return FALSE;
return TRUE;
}
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
easily. Oh well. */
asection *s;
void *vpp;
+ Elf_Internal_Sym *isym;
- s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
- sec, r_symndx);
- if (s == NULL)
+ isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+ abfd, r_symndx);
+ if (isym == NULL)
return FALSE;
+ 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;
}
/* 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);
}
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;
- }
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, relend, howto, contents);
if (info->relocatable)
continue;
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
elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
/* pr_pid */
- elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
+ elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24);
/* pr_reg */
offset = 72;
return plt->vma + PLT_FIRST_ENTRY_SIZE + i * PLT_ENTRY_SIZE;
}
+static bfd_boolean
+elf32_s390_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+{
+ elf_elfheader (obfd)->e_flags |= elf_elfheader (ibfd)->e_flags;
+ return TRUE;
+}
+
#define TARGET_BIG_SYM bfd_elf32_s390_vec
#define TARGET_BIG_NAME "elf32-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_elf32_bfd_reloc_type_lookup elf_s390_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup elf_s390_reloc_name_lookup
+#define bfd_elf32_bfd_merge_private_bfd_data elf32_s390_merge_private_bfd_data
+
#define elf_backend_adjust_dynamic_symbol elf_s390_adjust_dynamic_symbol
#define elf_backend_check_relocs elf_s390_check_relocs
#define elf_backend_copy_indirect_symbol elf_s390_copy_indirect_symbol