2012-07-13 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>

* elf64-s390.c: Include elf-s390-common.c.
	(R_390_IRELATIVE): New reloc.
	(elf_s390_reloc_type_lookup): Support R_390_IRELATIVE.
	(RELA_ENTRY_SIZE): New macro.
	(elf_s390_link_hash_entry): New fields ifunc_resolver_address and
	*ifunc_resolver_section.
	(struct plt_entry): New struct.
	(struct elf_s390_obj_tdata): New field local_plt.
	(elf_s390_local_plt): New macro.
	(struct elf_s390_link_hash_table): New field irelifunc.
	(ELF64): New macro.
	(link_hash_newfunc): Initialize new fields.
	(elf_s390_check_relocs): Handle IFUNC symbols.
	(elf_s390_adjust_dynamic_symbol): Don't do anything for IFUNC
	symbols.
	(allocate_dynrelocs): Call s390_elf_allocate_ifunc_dyn_relocs for
	IFUNC symbols.
	(elf_s390_size_dynamic_sections): Handle IFUNC symbols.
	(elf_s390_relocate_section): Likewise.
	(elf_s390_finish_dynamic_symbol): Likewise.
	(elf_s390_finish_dynamic_sections): Handle local IFUNC symbols.
	(elf_s390_finish_ifunc_symbol): New function.
	(elf_s390_gc_sweep_hook): Handle local plt entries.
	(elf_backend_add_symbol_hook): Define.
	* elf32-s390.c: See elf64-s390.c changes.
	* elf-s390-common.c: New file.
	* bfd-in2.h (BFD_RELOC_390_IRELATIVE): New enum field.
	* libbfd.h (BFD_RELOC_390_IRELATIVE): New entry for
	BFD_RELOC_390_IRELATIVE.
	* reloc.c (BFD_RELOC_390_IRELATIVE): Document new relocation.

2012-07-13  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* elf/s390.h (START_RELOC_NUMBERS): Define R_390_IRELATIVE reloc.

2012-07-13  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* emulparams/elf_s390.sh (IREL_IN_PLT): Define.
	* emulparams/elf64_s390.sh (IREL_IN_PLT): Define.
This commit is contained in:
Andreas Krebbel 2012-07-13 15:47:27 +00:00
parent 2c3fc38946
commit 470b557aaf
12 changed files with 1514 additions and 277 deletions

View File

@ -1,3 +1,36 @@
2012-07-13 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* elf64-s390.c: Include elf-s390-common.c.
(R_390_IRELATIVE): New reloc.
(elf_s390_reloc_type_lookup): Support R_390_IRELATIVE.
(RELA_ENTRY_SIZE): New macro.
(elf_s390_link_hash_entry): New fields ifunc_resolver_address and
*ifunc_resolver_section.
(struct plt_entry): New struct.
(struct elf_s390_obj_tdata): New field local_plt.
(elf_s390_local_plt): New macro.
(struct elf_s390_link_hash_table): New field irelifunc.
(ELF64): New macro.
(link_hash_newfunc): Initialize new fields.
(elf_s390_check_relocs): Handle IFUNC symbols.
(elf_s390_adjust_dynamic_symbol): Don't do anything for IFUNC
symbols.
(allocate_dynrelocs): Call s390_elf_allocate_ifunc_dyn_relocs for
IFUNC symbols.
(elf_s390_size_dynamic_sections): Handle IFUNC symbols.
(elf_s390_relocate_section): Likewise.
(elf_s390_finish_dynamic_symbol): Likewise.
(elf_s390_finish_dynamic_sections): Handle local IFUNC symbols.
(elf_s390_finish_ifunc_symbol): New function.
(elf_s390_gc_sweep_hook): Handle local plt entries.
(elf_backend_add_symbol_hook): Define.
* elf32-s390.c: See elf64-s390.c changes.
* elf-s390-common.c: New file.
* bfd-in2.h (BFD_RELOC_390_IRELATIVE): New enum field.
* libbfd.h (BFD_RELOC_390_IRELATIVE): New entry for
BFD_RELOC_390_IRELATIVE.
* reloc.c (BFD_RELOC_390_IRELATIVE): Document new relocation.
2012-07-13 Nick Clifton <nickc@redhat.com>
* aix386-core.c: Remove use of PTR and PARAMS macros.

View File

@ -4293,6 +4293,7 @@ in .byte hlo8(symbol) */
BFD_RELOC_390_GOT20,
BFD_RELOC_390_GOTPLT20,
BFD_RELOC_390_TLS_GOTIE20,
BFD_RELOC_390_IRELATIVE,
/* Score relocations
Low 16 bit for load/store */

243
bfd/elf-s390-common.c Normal file
View File

@ -0,0 +1,243 @@
/* IBM S/390-specific support for ELF 32 and 64 bit functions
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2011, 2012 Free Software Foundation, Inc.
Contributed by Andreas Krebbel.
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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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. */
/* Return TRUE if H is an IFUNC symbol. Simply checking for the
symbol type might not be enough since it might get changed to
STT_FUNC for pointer equality reasons. */
static inline bfd_boolean
s390_is_ifunc_symbol_p (struct elf_link_hash_entry *h)
{
struct elf_s390_link_hash_entry *eh = (struct elf_s390_link_hash_entry*)h;
return h->type == STT_GNU_IFUNC || eh->ifunc_resolver_address != 0;
}
/* Create sections needed by STT_GNU_IFUNC symbol. */
static bfd_boolean
s390_elf_create_ifunc_sections (bfd *abfd, struct bfd_link_info *info)
{
flagword flags;
asection *s;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
struct elf_link_hash_table *htab = elf_hash_table (info);
if (htab->iplt != NULL)
return TRUE;
flags = bed->dynamic_sec_flags;
if (info->shared)
{
s = bfd_make_section_with_flags (abfd, ".rela.ifunc",
flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s,
bed->s->log_file_align))
return FALSE;
htab->irelifunc = s;
}
/* Create .iplt, .rel[a].iplt, and .igot.plt. */
s = bfd_make_section_with_flags (abfd, ".iplt",
flags | SEC_CODE | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
return FALSE;
htab->iplt = s;
s = bfd_make_section_with_flags (abfd, ".rela.iplt", flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s,
bed->s->log_file_align))
return FALSE;
htab->irelplt = s;
s = bfd_make_section_with_flags (abfd, ".igot.plt", flags);
if (s == NULL
|| !bfd_set_section_alignment (abfd, s,
bed->s->log_file_align))
return FALSE;
htab->igotplt = s;
return TRUE;
}
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs against a STT_GNU_IFUNC symbol definition. */
static bfd_boolean
s390_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
struct elf_link_hash_entry *h,
struct elf_dyn_relocs **head)
{
struct elf_dyn_relocs *p;
struct elf_link_hash_table *htab;
struct elf_s390_link_hash_entry *eh = (struct elf_s390_link_hash_entry*)h;
htab = elf_hash_table (info);
eh->ifunc_resolver_address = h->root.u.def.value;
eh->ifunc_resolver_section = h->root.u.def.section;
/* Support garbage collection against STT_GNU_IFUNC symbols. */
if (h->plt.refcount <= 0 && h->got.refcount <= 0)
{
/* When building shared library, we need to handle the case
where it is marked with regular reference, but not non-GOT
reference. It may happen if we didn't see STT_GNU_IFUNC
symbol at the time when checking relocations. */
if (info->shared
&& !h->non_got_ref
&& h->ref_regular)
for (p = *head; p != NULL; p = p->next)
if (p->count)
{
h->non_got_ref = 1;
goto keep;
}
h->got = htab->init_got_offset;
h->plt = htab->init_plt_offset;
*head = NULL;
return TRUE;
}
/* Return and discard space for dynamic relocations against it if
it is never referenced in a non-shared object. */
if (!h->ref_regular)
{
if (h->plt.refcount > 0
|| h->got.refcount > 0)
abort ();
h->got = htab->init_got_offset;
h->plt = htab->init_plt_offset;
*head = NULL;
return TRUE;
}
keep:
/* Without checking h->plt.refcount here we allocate a PLT slot.
When setting plt.refcount in check_relocs it might not have been
known that this will be an IFUNC symol. */
h->plt.offset = htab->iplt->size;
h->needs_plt = 1;
htab->iplt->size += PLT_ENTRY_SIZE;
htab->igotplt->size += GOT_ENTRY_SIZE;
htab->irelplt->size += RELA_ENTRY_SIZE;
htab->irelplt->reloc_count++;
/* In order to make pointer equality work with IFUNC symbols defined
in a non-PIE executable and referenced in a shared lib, we turn
the symbol into a STT_FUNC symbol and make the symbol value to
point to the IPLT slot. That way the referencing shared lib will
always get the PLT slot address when resolving the respective
R_390_GLOB_DAT/R_390_64 relocs on that symbol. */
if (info->executable && !info->shared && h->def_regular && h->ref_dynamic)
{
h->root.u.def.section = htab->iplt;
h->root.u.def.value = h->plt.offset;
h->size = PLT_ENTRY_SIZE;
h->type = STT_FUNC;
}
/* We need dynamic relocation for STT_GNU_IFUNC symbol only when
there is a non-GOT reference in a shared object. */
if (!info->shared || !h->non_got_ref)
*head = NULL;
/* Finally, allocate space. */
p = *head;
if (p != NULL)
{
bfd_size_type count = 0;
do
{
count += p->count;
p = p->next;
}
while (p != NULL);
htab->irelifunc->size += count * RELA_ENTRY_SIZE;
}
/* Decide whether the got.iplt slot can be used. This has to be
avoided if the values in the GOT slots could differ for pointer
equality reasons. */
if (h->got.refcount <= 0
|| (info->shared
&& (h->dynindx == -1 || h->forced_local))
|| (info->executable && info->shared)
|| htab->sgot == NULL)
{
/* Use .got.iplt. */
h->got.offset = (bfd_vma) -1;
}
else
{
h->got.offset = htab->sgot->size;
htab->sgot->size += GOT_ENTRY_SIZE;
if (info->shared)
htab->srelgot->size += RELA_ENTRY_SIZE;
}
return TRUE;
}
static bfd_boolean
elf_s390_allocate_local_syminfo (bfd *abfd, Elf_Internal_Shdr *symtab_hdr)
{
bfd_size_type size;
size = symtab_hdr->sh_info;
size *= (sizeof (bfd_signed_vma) /* local got */
+ sizeof (struct plt_entry) /* local plt */
+ sizeof(char)); /* local tls type */
elf_local_got_refcounts (abfd) = ((bfd_signed_vma *)
bfd_zalloc (abfd, size));
if (elf_local_got_refcounts (abfd) == NULL)
return FALSE;
elf_s390_local_plt (abfd)
= (struct plt_entry*)(elf_local_got_refcounts (abfd)
+ symtab_hdr->sh_info);
elf_s390_local_got_tls_type (abfd)
= (char *) (elf_s390_local_plt (abfd) + symtab_hdr->sh_info);
return TRUE;
}
/* Pick ELFOSABI_GNU if IFUNC symbols are used. */
static bfd_boolean
elf_s390_add_symbol_hook (bfd *abfd,
struct bfd_link_info *info,
Elf_Internal_Sym *sym,
const char **namep ATTRIBUTE_UNUSED,
flagword *flagsp ATTRIBUTE_UNUSED,
asection **secp ATTRIBUTE_UNUSED,
bfd_vma *valp ATTRIBUTE_UNUSED)
{
if ((abfd->flags & DYNAMIC) == 0
&& ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
return TRUE;
}

File diff suppressed because it is too large Load Diff

View File

@ -169,6 +169,9 @@ static reloc_howto_type elf_howto_table[] =
s390_elf_ldisp_reloc, "R_390_GOTPLT20", FALSE, 0,0x0fffff00, FALSE),
HOWTO(R_390_TLS_GOTIE20, 0, 2, 20, FALSE, 8, complain_overflow_dont,
s390_elf_ldisp_reloc, "R_390_TLS_GOTIE20", FALSE, 0,0x0fffff00, FALSE),
HOWTO(R_390_IRELATIVE, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_390_IRELATIVE", FALSE, 0, MINUS_ONE, FALSE),
};
/* GNU extension to record C++ vtable hierarchy. */
@ -295,6 +298,8 @@ elf_s390_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
return &elf_howto_table[(int) R_390_GOTPLT20];
case BFD_RELOC_390_TLS_GOTIE20:
return &elf_howto_table[(int) R_390_TLS_GOTIE20];
case BFD_RELOC_390_IRELATIVE:
return &elf_howto_table[(int) R_390_IRELATIVE];
case BFD_RELOC_VTABLE_INHERIT:
return &elf64_s390_vtinherit_howto;
case BFD_RELOC_VTABLE_ENTRY:
@ -450,6 +455,8 @@ elf_s390_is_local_label_name (bfd *abfd, const char *name)
#define GOT_ENTRY_SIZE 8
#define RELA_ENTRY_SIZE sizeof (Elf64_External_Rela)
/* The first three entries in a procedure linkage table are reserved,
and the initial contents are unimportant (we zero them out).
Subsequent entries look like this. See the SVR4 ABI 386
@ -552,17 +559,43 @@ struct elf_s390_link_hash_entry
#define GOT_TLS_IE 3
#define GOT_TLS_IE_NLT 3
unsigned char tls_type;
/* For pointer equality reasons we might need to change the symbol
type from STT_GNU_IFUNC to STT_FUNC together with its value and
section entry. So after alloc_dynrelocs only these values should
be used. In order to check whether a symbol is IFUNC use
s390_is_ifunc_symbol_p. */
bfd_vma ifunc_resolver_address;
asection *ifunc_resolver_section;
};
#define elf_s390_hash_entry(ent) \
((struct elf_s390_link_hash_entry *)(ent))
/* This structure represents an entry in the local PLT list needed for
local IFUNC symbols. */
struct plt_entry
{
/* The section of the local symbol.
Set in relocate_section and used in finish_dynamic_sections. */
asection *sec;
union
{
bfd_signed_vma refcount;
bfd_vma offset;
} plt;
};
/* NOTE: Keep this structure in sync with
the one declared in elf32-s390.c. */
struct elf_s390_obj_tdata
{
struct elf_obj_tdata root;
/* A local PLT is needed for ifunc symbols. */
struct plt_entry *local_plt;
/* TLS type for each local got entry. */
char *local_got_tls_type;
};
@ -570,6 +603,9 @@ struct elf_s390_obj_tdata
#define elf_s390_tdata(abfd) \
((struct elf_s390_obj_tdata *) (abfd)->tdata.any)
#define elf_s390_local_plt(abfd) \
(elf_s390_tdata (abfd)->local_plt)
#define elf_s390_local_got_tls_type(abfd) \
(elf_s390_tdata (abfd)->local_got_tls_type)
@ -601,6 +637,7 @@ struct elf_s390_link_hash_table
/* Short-cuts to get to dynamic linker sections. */
asection *sdynbss;
asection *srelbss;
asection *irelifunc;
union {
bfd_signed_vma refcount;
@ -617,6 +654,9 @@ struct elf_s390_link_hash_table
(elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
== S390_ELF_DATA ? ((struct elf_s390_link_hash_table *) ((p)->hash)) : NULL)
#define ELF64 1
#include "elf-s390-common.c"
/* Create an entry in an s390 ELF linker hash table. */
static struct bfd_hash_entry *
@ -644,6 +684,8 @@ link_hash_newfunc (struct bfd_hash_entry *entry,
eh->dyn_relocs = NULL;
eh->gotplt_refcount = 0;
eh->tls_type = GOT_UNKNOWN;
eh->ifunc_resolver_address = 0;
eh->ifunc_resolver_section = NULL;
}
return entry;
@ -871,6 +913,7 @@ elf_s390_check_relocs (bfd *abfd,
unsigned int r_type;
unsigned long r_symndx;
struct elf_link_hash_entry *h;
Elf_Internal_Sym *isym;
r_symndx = ELF64_R_SYM (rel->r_info);
@ -883,7 +926,31 @@ elf_s390_check_relocs (bfd *abfd,
}
if (r_symndx < symtab_hdr->sh_info)
h = NULL;
{
/* A local symbol. */
isym = bfd_sym_from_r_symndx (&htab->sym_cache,
abfd, r_symndx);
if (isym == NULL)
return FALSE;
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
{
struct plt_entry *plt;
if (!s390_elf_create_ifunc_sections (htab->elf.dynobj, info))
return FALSE;
if (local_got_refcounts == NULL)
{
if (!elf_s390_allocate_local_syminfo (abfd, symtab_hdr))
return FALSE;
local_got_refcounts = elf_local_got_refcounts (abfd);
}
plt = elf_s390_local_plt (abfd);
plt[r_symndx].plt.refcount++;
}
h = NULL;
}
else
{
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
@ -921,18 +988,11 @@ elf_s390_check_relocs (bfd *abfd,
if (h == NULL
&& local_got_refcounts == NULL)
{
bfd_size_type size;
size = symtab_hdr->sh_info;
size *= (sizeof (bfd_signed_vma) + sizeof(char));
local_got_refcounts = ((bfd_signed_vma *)
bfd_zalloc (abfd, size));
if (local_got_refcounts == NULL)
if (!elf_s390_allocate_local_syminfo (abfd, symtab_hdr))
return FALSE;
elf_local_got_refcounts (abfd) = local_got_refcounts;
elf_s390_local_got_tls_type (abfd)
= (char *) (local_got_refcounts + symtab_hdr->sh_info);
local_got_refcounts = elf_local_got_refcounts (abfd);
}
/* Fall through. */
case R_390_GOTOFF16:
case R_390_GOTOFF32:
@ -948,6 +1008,25 @@ elf_s390_check_relocs (bfd *abfd,
}
}
if (h != NULL)
{
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
if (!s390_elf_create_ifunc_sections (htab->elf.dynobj, info))
return FALSE;
/* Make sure an IFUNC symbol defined in a non-shared object
always gets a PLT slot. */
if (s390_is_ifunc_symbol_p (h) && h->def_regular)
{
/* The symbol is called by the dynamic loader in order
to resolve the relocation. So it is in fact also
referenced. */
h->ref_regular = 1;
h->needs_plt = 1;
}
}
switch (r_type)
{
case R_390_GOTOFF16:
@ -955,7 +1034,10 @@ elf_s390_check_relocs (bfd *abfd,
case R_390_GOTOFF64:
case R_390_GOTPC:
case R_390_GOTPCDBL:
/* Got is created, nothing to be done. */
/* These relocs do not need a GOT slot. They just load the
GOT pointer itself or address something else relative to
the GOT. Since the GOT pointer has been set up above we
are done. */
break;
case R_390_PLT16DBL:
@ -1102,7 +1184,7 @@ elf_s390_check_relocs (bfd *abfd,
case R_390_PC32:
case R_390_PC32DBL:
case R_390_PC64:
if (h != NULL && !info->shared)
if (h != NULL)
{
/* If this reloc is in a read-only section, we might
need a copy reloc. We can't check reliably at this
@ -1112,9 +1194,12 @@ elf_s390_check_relocs (bfd *abfd,
adjust_dynamic_symbol. */
h->non_got_ref = 1;
/* We may need a .plt entry if the function this reloc
refers to is in a shared lib. */
h->plt.refcount += 1;
if (!info->shared)
{
/* We may need a .plt entry if the function this reloc
refers to is in a shared lib. */
h->plt.refcount += 1;
}
}
/* If we are creating a shared library, and this is a reloc
@ -1187,7 +1272,6 @@ elf_s390_check_relocs (bfd *abfd,
easily. Oh well. */
asection *s;
void *vpp;
Elf_Internal_Sym *isym;
isym = bfd_sym_from_r_symndx (&htab->sym_cache,
abfd, r_symndx);
@ -1327,6 +1411,23 @@ elf_s390_gc_sweep_hook (bfd *abfd,
break;
}
}
else
{
Elf_Internal_Sym *isym;
/* A local symbol. */
isym = bfd_sym_from_r_symndx (&htab->sym_cache,
abfd, r_symndx);
if (isym == NULL)
return FALSE;
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
{
struct plt_entry *plt = elf_s390_local_plt (abfd);
if (plt[r_symndx].plt.refcount > 0)
plt[r_symndx].plt.refcount--;
}
}
r_type = ELF64_R_TYPE (rel->r_info);
r_type = elf_s390_tls_transition (info, r_type, h != NULL);
@ -1459,6 +1560,10 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_s390_link_hash_table *htab;
asection *s;
/* STT_GNU_IFUNC symbol must go through PLT. */
if (s390_is_ifunc_symbol_p (h))
return TRUE;
/* If this is a function, put it in the procedure linkage table. We
will fill in the contents of the procedure linkage table later
(although we could actually do it here). */
@ -1585,7 +1690,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h,
{
struct bfd_link_info *info;
struct elf_s390_link_hash_table *htab;
struct elf_s390_link_hash_entry *eh;
struct elf_s390_link_hash_entry *eh = (struct elf_s390_link_hash_entry *)h;
struct elf_dyn_relocs *p;
if (h->root.type == bfd_link_hash_indirect)
@ -1596,8 +1701,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h,
if (htab == NULL)
return FALSE;
if (htab->elf.dynamic_sections_created
&& h->plt.refcount > 0)
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
here if it is defined and referenced in a non-shared object. */
if (s390_is_ifunc_symbol_p (h) && h->def_regular)
return s390_elf_allocate_ifunc_dyn_relocs (info, h,
&eh->dyn_relocs);
else if (htab->elf.dynamic_sections_created
&& h->plt.refcount > 0)
{
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
@ -1714,7 +1824,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h,
else
h->got.offset = (bfd_vma) -1;
eh = (struct elf_s390_link_hash_entry *) h;
if (eh->dyn_relocs == NULL)
return TRUE;
@ -1871,6 +1980,8 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
bfd_size_type locsymcount;
Elf_Internal_Shdr *symtab_hdr;
asection *srela;
struct plt_entry *local_plt;
unsigned int i;
if (! is_s390_elf (ibfd))
continue;
@ -1923,6 +2034,20 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
else
*local_got = (bfd_vma) -1;
}
local_plt = elf_s390_local_plt (ibfd);
for (i = 0; i < symtab_hdr->sh_info; i++)
{
if (local_plt[i].plt.refcount > 0)
{
local_plt[i].plt.offset = htab->elf.iplt->size;
htab->elf.iplt->size += PLT_ENTRY_SIZE;
htab->elf.igotplt->size += GOT_ENTRY_SIZE;
htab->elf.irelplt->size += sizeof (Elf64_External_Rela);
}
else
local_plt[i].plt.offset = (bfd_vma) -1;
}
}
if (htab->tls_ldm_got.refcount > 0)
@ -1951,7 +2076,10 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
if (s == htab->elf.splt
|| s == htab->elf.sgot
|| s == htab->elf.sgotplt
|| s == htab->sdynbss)
|| s == htab->sdynbss
|| s == htab->elf.iplt
|| s == htab->elf.igotplt
|| s == htab->irelifunc)
{
/* Strip this section if we don't need it; see the
comment below. */
@ -2141,6 +2269,7 @@ elf_s390_relocate_section (bfd *output_bfd,
bfd_boolean unresolved_reloc;
bfd_reloc_status_type r;
int tls_type;
asection *base_got = htab->elf.sgot;
r_type = ELF64_R_TYPE (rel->r_info);
if (r_type == (int) R_390_GNU_VTINHERIT
@ -2163,7 +2292,55 @@ elf_s390_relocate_section (bfd *output_bfd,
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
{
struct plt_entry *local_plt = elf_s390_local_plt (input_bfd);
if (local_plt == NULL)
return FALSE;
/* Address of the PLT slot. */
relocation = (htab->elf.iplt->output_section->vma
+ htab->elf.iplt->output_offset
+ local_plt[r_symndx].plt.offset);
switch (r_type)
{
case R_390_GOTPLT12:
case R_390_GOTPLT16:
case R_390_GOTPLT20:
case R_390_GOTPLT32:
case R_390_GOTPLT64:
case R_390_GOTPLTENT:
case R_390_GOT12:
case R_390_GOT16:
case R_390_GOT20:
case R_390_GOT32:
case R_390_GOT64:
case R_390_GOTENT:
{
/* Write the PLT slot address into the GOT slot. */
bfd_put_64 (output_bfd, relocation,
htab->elf.sgot->contents +
local_got_offsets[r_symndx]);
relocation = (local_got_offsets[r_symndx] +
htab->elf.sgot->output_offset);
if (r_type == R_390_GOTENT || r_type == R_390_GOTPLTENT)
relocation += htab->elf.sgot->output_section->vma;
break;
}
default:
break;
}
/* The output section is needed later in
finish_dynamic_section when creating the dynamic
relocation. */
local_plt[r_symndx].sec = sec;
goto do_relocation;
}
else
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
}
else
{
@ -2203,18 +2380,28 @@ elf_s390_relocate_section (bfd *output_bfd,
{
bfd_vma plt_index;
/* Calc. index no.
Current offset - size first entry / entry size. */
plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) /
PLT_ENTRY_SIZE;
if (s390_is_ifunc_symbol_p (h))
{
plt_index = h->plt.offset / PLT_ENTRY_SIZE;
relocation = (plt_index * GOT_ENTRY_SIZE +
htab->elf.igotplt->output_offset);
if (r_type == R_390_GOTPLTENT)
relocation += htab->elf.igotplt->output_section->vma;
}
else
{
/* Calc. index no.
Current offset - size first entry / entry size. */
plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) /
PLT_ENTRY_SIZE;
/* Offset in GOT is PLT index plus GOT headers(3) times 4,
addr & GOT addr. */
relocation = (plt_index + 3) * GOT_ENTRY_SIZE;
/* Offset in GOT is PLT index plus GOT headers(3)
times 4, addr & GOT addr. */
relocation = (plt_index + 3) * GOT_ENTRY_SIZE;
if (r_type == R_390_GOTPLTENT)
relocation += htab->elf.sgot->output_section->vma;
}
unresolved_reloc = FALSE;
if (r_type == R_390_GOTPLTENT)
relocation += htab->elf.sgot->output_section->vma;
break;
}
/* Fall through. */
@ -2227,7 +2414,7 @@ elf_s390_relocate_section (bfd *output_bfd,
case R_390_GOTENT:
/* Relocation is to the entry for this symbol in the global
offset table. */
if (htab->elf.sgot == NULL)
if (base_got == NULL)
abort ();
if (h != NULL)
@ -2236,11 +2423,29 @@ elf_s390_relocate_section (bfd *output_bfd,
off = h->got.offset;
dyn = htab->elf.dynamic_sections_created;
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
|| (info->shared
&& SYMBOL_REFERENCES_LOCAL (info, h))
|| (ELF_ST_VISIBILITY (h->other)
&& h->root.type == bfd_link_hash_undefweak))
if (s390_is_ifunc_symbol_p (h))
{
BFD_ASSERT (h->plt.offset != (bfd_vma) -1);
if (off == (bfd_vma)-1)
{
/* No explicit GOT usage so redirect to the
got.iplt slot. */
base_got = htab->elf.igotplt;
off = h->plt.offset / PLT_ENTRY_SIZE * GOT_ENTRY_SIZE;
}
else
{
/* Explicit GOT slots must contain the address
of the PLT slot. This will be handled in
finish_dynamic_symbol. */
}
}
else if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
|| (info->shared
&& SYMBOL_REFERENCES_LOCAL (info, h))
|| (ELF_ST_VISIBILITY (h->other)
&& h->root.type == bfd_link_hash_undefweak))
{
/* This is actually a static link, or it is a
-Bsymbolic link and the symbol is defined
@ -2259,7 +2464,7 @@ elf_s390_relocate_section (bfd *output_bfd,
else
{
bfd_put_64 (output_bfd, relocation,
htab->elf.sgot->contents + off);
base_got->contents + off);
h->got.offset |= 1;
}
}
@ -2310,7 +2515,7 @@ elf_s390_relocate_section (bfd *output_bfd,
if (off >= (bfd_vma) -2)
abort ();
relocation = htab->elf.sgot->output_offset + off;
relocation = base_got->output_offset + off;
/* For @GOTENT the relocation is against the offset between
the instruction and the symbols entry in the GOT and not
@ -2318,7 +2523,7 @@ elf_s390_relocate_section (bfd *output_bfd,
add the vma of the GOT to get the correct value. */
if ( r_type == R_390_GOTENT
|| r_type == R_390_GOTPLTENT)
relocation += htab->elf.sgot->output_section->vma;
relocation += base_got->output_section->vma;
break;
@ -2356,17 +2561,21 @@ elf_s390_relocate_section (bfd *output_bfd,
break;
if (h->plt.offset == (bfd_vma) -1
|| htab->elf.splt == NULL)
|| (htab->elf.splt == NULL && htab->elf.iplt == NULL))
{
/* We didn't make a PLT entry for this symbol. This
happens when statically linking PIC code, or when
using -Bsymbolic. */
break;
}
relocation = (htab->elf.splt->output_section->vma
+ htab->elf.splt->output_offset
+ h->plt.offset);
if (s390_is_ifunc_symbol_p (h))
relocation = (htab->elf.iplt->output_section->vma
+ htab->elf.iplt->output_offset
+ h->plt.offset);
else
relocation = (htab->elf.splt->output_section->vma
+ htab->elf.splt->output_offset
+ h->plt.offset);
unresolved_reloc = FALSE;
break;
@ -2386,10 +2595,16 @@ elf_s390_relocate_section (bfd *output_bfd,
break;
}
relocation = (htab->elf.splt->output_section->vma
+ htab->elf.splt->output_offset
+ h->plt.offset
- htab->elf.sgot->output_section->vma);
if (s390_is_ifunc_symbol_p (h))
relocation = (htab->elf.iplt->output_section->vma
+ htab->elf.iplt->output_offset
+ h->plt.offset
- htab->elf.sgot->output_section->vma);
else
relocation = (htab->elf.splt->output_section->vma
+ htab->elf.splt->output_offset
+ h->plt.offset
- htab->elf.sgot->output_section->vma);
unresolved_reloc = FALSE;
break;
@ -2402,6 +2617,68 @@ elf_s390_relocate_section (bfd *output_bfd,
case R_390_PC32:
case R_390_PC32DBL:
case R_390_PC64:
if (h != NULL
&& s390_is_ifunc_symbol_p (h)
&& h->def_regular)
{
if (!info->shared || !h->non_got_ref)
{
/* For a non-shared object STT_GNU_IFUNC symbol must
go through PLT. */
relocation = (htab->elf.iplt->output_section->vma
+ htab->elf.iplt->output_offset
+ h ->plt.offset);
goto do_relocation;
}
else
{
/* For shared objects a runtime relocation is needed. */
Elf_Internal_Rela outrel;
asection *sreloc;
/* Need a dynamic relocation to get the real function
address. */
outrel.r_offset = _bfd_elf_section_offset (output_bfd,
info,
input_section,
rel->r_offset);
if (outrel.r_offset == (bfd_vma) -1
|| outrel.r_offset == (bfd_vma) -2)
abort ();
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
if (h->dynindx == -1
|| h->forced_local
|| info->executable)
{
/* This symbol is resolved locally. */
outrel.r_info = ELF64_R_INFO (0, R_390_IRELATIVE);
outrel.r_addend = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
}
else
{
outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
outrel.r_addend = 0;
}
sreloc = htab->elf.irelifunc;
elf_append_rela (output_bfd, sreloc, &outrel);
/* If this reloc is against an external symbol, we
do not want to fiddle with the addend. Otherwise,
we need to include the symbol value so that it
becomes an addend for the dynamic reloc. For an
internal symbol, we have updated addend. */
continue;
}
}
if ((input_section->flags & SEC_ALLOC) == 0)
break;
@ -2887,6 +3164,8 @@ elf_s390_relocate_section (bfd *output_bfd,
howto->name,
h->root.root.string);
do_relocation:
if (r_type == R_390_20
|| r_type == R_390_GOT20
|| r_type == R_390_GOTPLT20
@ -2943,6 +3222,92 @@ elf_s390_relocate_section (bfd *output_bfd,
return TRUE;
}
/* Generate the PLT slots together with the dynamic relocations needed
for IFUNC symbols. */
static void
elf_s390_finish_ifunc_symbol (bfd *output_bfd,
struct bfd_link_info *info,
struct elf_link_hash_entry *h,
struct elf_s390_link_hash_table *htab,
bfd_vma plt_offset,
bfd_vma resolver_address)
{
bfd_vma plt_index;
bfd_vma got_offset;
Elf_Internal_Rela rela;
bfd_byte *loc;
asection *plt, *gotplt, *relplt;
if (htab->elf.iplt == NULL
|| htab->elf.igotplt == NULL
|| htab->elf.irelplt == NULL)
abort ();
/* Index of the PLT slot within iplt section. */
plt_index = plt_offset / PLT_ENTRY_SIZE;
plt = htab->elf.iplt;
/* Offset into the igot.plt section. */
got_offset = plt_index * GOT_ENTRY_SIZE;
gotplt = htab->elf.igotplt;
relplt = htab->elf.irelplt;
/* Fill in the blueprint of a PLT. */
memcpy (plt->contents + plt_offset, elf_s390x_plt_entry,
PLT_ENTRY_SIZE);
/* Fixup the relative address to the GOT entry */
bfd_put_32 (output_bfd,
(gotplt->output_section->vma +
gotplt->output_offset + got_offset
- (plt->output_section->vma +
plt->output_offset +
plt_offset))/2,
plt->contents + plt_offset + 2);
/* Fixup the relative branch to PLT 0 */
bfd_put_32 (output_bfd, - (plt->output_offset +
(PLT_ENTRY_SIZE * plt_index) + 22)/2,
plt->contents + plt_offset + 24);
/* Fixup offset into .rela.plt section. */
bfd_put_32 (output_bfd, relplt->output_offset +
plt_index * sizeof (Elf64_External_Rela),
plt->contents + plt_offset + 28);
/* Fill in the entry in the global offset table.
Points to instruction after GOT offset. */
bfd_put_64 (output_bfd,
(plt->output_section->vma
+ plt->output_offset
+ plt_offset
+ 14),
gotplt->contents + got_offset);
/* Fill in the entry in the .rela.plt section. */
rela.r_offset = (gotplt->output_section->vma
+ gotplt->output_offset
+ got_offset);
if (!h
|| h->dynindx == -1
|| ((info->executable
|| ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
&& h->def_regular))
{
/* The symbol can be locally resolved. */
rela.r_info = ELF64_R_INFO (0, R_390_IRELATIVE);
rela.r_addend = resolver_address;
}
else
{
rela.r_info = ELF64_R_INFO (h->dynindx, R_390_JMP_SLOT);
rela.r_addend = 0;
}
loc = relplt->contents + plt_index * sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
}
/* Finish up dynamic symbol handling. We set the contents of various
dynamic sections here. */
@ -2953,6 +3318,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
Elf_Internal_Sym *sym)
{
struct elf_s390_link_hash_table *htab;
struct elf_s390_link_hash_entry *eh = (struct elf_s390_link_hash_entry*)h;
htab = elf_s390_hash_table (info);
if (htab == NULL)
@ -2967,65 +3333,82 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
/* This symbol has an entry in the procedure linkage table. Set
it up. */
if (h->dynindx == -1
|| htab->elf.splt == NULL
|| htab->elf.sgotplt == NULL
|| htab->elf.srelplt == NULL)
abort ();
/* Calc. index no.
Current offset - size first entry / entry size. */
plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) / PLT_ENTRY_SIZE;
/* Offset in GOT is PLT index plus GOT headers(3) times 8,
addr & GOT addr. */
got_offset = (plt_index + 3) * GOT_ENTRY_SIZE;
/* Fill in the blueprint of a PLT. */
memcpy (htab->elf.splt->contents + h->plt.offset, elf_s390x_plt_entry,
PLT_ENTRY_SIZE);
/* Fixup the relative address to the GOT entry */
bfd_put_32 (output_bfd,
(htab->elf.sgotplt->output_section->vma +
htab->elf.sgotplt->output_offset + got_offset
- (htab->elf.splt->output_section->vma + h->plt.offset))/2,
htab->elf.splt->contents + h->plt.offset + 2);
/* Fixup the relative branch to PLT 0 */
bfd_put_32 (output_bfd, - (PLT_FIRST_ENTRY_SIZE +
(PLT_ENTRY_SIZE * plt_index) + 22)/2,
htab->elf.splt->contents + h->plt.offset + 24);
/* Fixup offset into .rela.plt section. */
bfd_put_32 (output_bfd, plt_index * sizeof (Elf64_External_Rela),
htab->elf.splt->contents + h->plt.offset + 28);
/* Fill in the entry in the global offset table.
Points to instruction after GOT offset. */
bfd_put_64 (output_bfd,
(htab->elf.splt->output_section->vma
+ htab->elf.splt->output_offset
+ h->plt.offset
+ 14),
htab->elf.sgotplt->contents + got_offset);
/* Fill in the entry in the .rela.plt section. */
rela.r_offset = (htab->elf.sgotplt->output_section->vma
+ htab->elf.sgotplt->output_offset
+ got_offset);
rela.r_info = ELF64_R_INFO (h->dynindx, R_390_JMP_SLOT);
rela.r_addend = 0;
loc = htab->elf.srelplt->contents + plt_index * sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
if (!h->def_regular)
if (s390_is_ifunc_symbol_p (h))
{
/* Mark the symbol as undefined, rather than as defined in
the .plt section. Leave the value alone. This is a clue
for the dynamic linker, to make function pointer
comparisons work between an application and shared
library. */
sym->st_shndx = SHN_UNDEF;
/* If we can resolve the IFUNC symbol locally we generate an
IRELATIVE reloc. */
elf_s390_finish_ifunc_symbol (output_bfd, info, h, htab, h->plt.offset,
eh->ifunc_resolver_address +
eh->ifunc_resolver_section->output_offset +
eh->ifunc_resolver_section->output_section->vma);
;
/* Fallthrough. Handling of explicit GOT slots of IFUNC
symbols is below. */
}
else
{
if (h->dynindx == -1
|| htab->elf.splt == NULL
|| htab->elf.sgotplt == NULL
|| htab->elf.srelplt == NULL)
abort ();
/* Calc. index no.
Current offset - size first entry / entry size. */
plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) / PLT_ENTRY_SIZE;
/* Offset in GOT is PLT index plus GOT headers(3) times 8,
addr & GOT addr. */
got_offset = (plt_index + 3) * GOT_ENTRY_SIZE;
/* Fill in the blueprint of a PLT. */
memcpy (htab->elf.splt->contents + h->plt.offset, elf_s390x_plt_entry,
PLT_ENTRY_SIZE);
/* Fixup the relative address to the GOT entry */
bfd_put_32 (output_bfd,
(htab->elf.sgotplt->output_section->vma +
htab->elf.sgotplt->output_offset + got_offset
- (htab->elf.splt->output_section->vma +
htab->elf.splt->output_offset +
h->plt.offset))/2,
htab->elf.splt->contents + h->plt.offset + 2);
/* Fixup the relative branch to PLT 0 */
bfd_put_32 (output_bfd, - (PLT_FIRST_ENTRY_SIZE +
(PLT_ENTRY_SIZE * plt_index) + 22)/2,
htab->elf.splt->contents + h->plt.offset + 24);
/* Fixup offset into .rela.plt section. */
bfd_put_32 (output_bfd, plt_index * sizeof (Elf64_External_Rela),
htab->elf.splt->contents + h->plt.offset + 28);
/* Fill in the entry in the global offset table.
Points to instruction after GOT offset. */
bfd_put_64 (output_bfd,
(htab->elf.splt->output_section->vma
+ htab->elf.splt->output_offset
+ h->plt.offset
+ 14),
htab->elf.sgotplt->contents + got_offset);
/* Fill in the entry in the .rela.plt section. */
rela.r_offset = (htab->elf.sgotplt->output_section->vma
+ htab->elf.sgotplt->output_offset
+ got_offset);
rela.r_info = ELF64_R_INFO (h->dynindx, R_390_JMP_SLOT);
rela.r_addend = 0;
loc = htab->elf.srelplt->contents + plt_index *
sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
if (!h->def_regular)
{
/* Mark the symbol as undefined, rather than as defined in
the .plt section. Leave the value alone. This is a clue
for the dynamic linker, to make function pointer
comparisons work between an application and shared
library. */
sym->st_shndx = SHN_UNDEF;
}
}
}
@ -3046,14 +3429,37 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
+ htab->elf.sgot->output_offset
+ (h->got.offset &~ (bfd_vma) 1));
/* If this is a static link, or it is a -Bsymbolic link and the
symbol is defined locally or was forced to be local because
of a version file, we just want to emit a RELATIVE reloc.
The entry in the global offset table will already have been
initialized in the relocate_section function. */
if (info->shared
if (h->def_regular && s390_is_ifunc_symbol_p (h))
{
if (info->shared)
{
/* An explicit GOT slot usage needs GLOB_DAT. If the
symbol references local the implicit got.iplt slot
will be used and the IRELATIVE reloc has been created
above. */
goto do_glob_dat;
}
else
{
/* For non-shared objects explicit GOT slots must be
filled with the PLT slot address for pointer
equality reasons. */
bfd_put_64 (output_bfd, (htab->elf.iplt->output_section->vma
+ htab->elf.iplt->output_offset
+ h->plt.offset),
htab->elf.sgot->contents + h->got.offset);
return TRUE;
}
}
else if (info->shared
&& SYMBOL_REFERENCES_LOCAL (info, h))
{
/* If this is a static link, or it is a -Bsymbolic link and
the symbol is defined locally or was forced to be local
because of a version file, we just want to emit a
RELATIVE reloc. The entry in the global offset table
will already have been initialized in the
relocate_section function. */
if (!h->def_regular)
return FALSE;
BFD_ASSERT((h->got.offset & 1) != 0);
@ -3065,6 +3471,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
else
{
BFD_ASSERT((h->got.offset & 1) == 0);
do_glob_dat:
bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgot->contents + h->got.offset);
rela.r_info = ELF64_R_INFO (h->dynindx, R_390_GLOB_DAT);
rela.r_addend = 0;
@ -3135,6 +3542,8 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
struct elf_s390_link_hash_table *htab;
bfd *dynobj;
asection *sdyn;
bfd *ibfd;
unsigned int i;
htab = elf_s390_hash_table (info);
if (htab == NULL)
@ -3228,6 +3637,38 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
elf_section_data (htab->elf.sgot->output_section)
->this_hdr.sh_entsize = 8;
}
/* Finish dynamic symbol for local IFUNC symbols. */
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
{
struct plt_entry *local_plt;
Elf_Internal_Sym *isym;
Elf_Internal_Shdr *symtab_hdr;
symtab_hdr = &elf_symtab_hdr (ibfd);
local_plt = elf_s390_local_plt (ibfd);
if (local_plt != NULL)
for (i = 0; i < symtab_hdr->sh_info; i++)
{
if (local_plt[i].plt.offset != (bfd_vma) -1)
{
asection *sec = local_plt[i].sec;
isym = bfd_sym_from_r_symndx (&htab->sym_cache, ibfd, i);
if (isym == NULL)
return FALSE;
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
elf_s390_finish_ifunc_symbol (output_bfd, info, NULL, htab,
local_plt[i].plt.offset,
isym->st_value
+ sec->output_section->vma
+ sec->output_offset);
}
}
}
return TRUE;
}
@ -3241,7 +3682,6 @@ elf_s390_plt_sym_val (bfd_vma i, const asection *plt,
return plt->vma + PLT_FIRST_ENTRY_SIZE + i * PLT_ENTRY_SIZE;
}
/* Why was the hash table entry size definition changed from
ARCH_SIZE/8 to 4? This breaks the 64 bit dynamic linker and
this is the only reason for the s390_elf64_size_info structure. */
@ -3316,6 +3756,7 @@ const struct elf_size_info s390_elf64_size_info =
#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
#define elf_backend_add_symbol_hook elf_s390_add_symbol_hook
#define bfd_elf64_mkobject elf_s390_mkobject
#define elf_backend_object_p elf_s390_object_p

View File

@ -1996,6 +1996,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_390_GOT20",
"BFD_RELOC_390_GOTPLT20",
"BFD_RELOC_390_TLS_GOTIE20",
"BFD_RELOC_390_IRELATIVE",
"BFD_RELOC_SCORE_GPREL15",
"BFD_RELOC_SCORE_DUMMY2",
"BFD_RELOC_SCORE_JMP",

View File

@ -4693,6 +4693,11 @@ ENUMX
ENUMDOC
Long displacement extension.
ENUM
BFD_RELOC_390_IRELATIVE
ENUMDOC
STT_GNU_IFUNC relocation.
ENUM
BFD_RELOC_SCORE_GPREL15
ENUMDOC

View File

@ -1,3 +1,7 @@
2012-07-13 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* elf/s390.h (START_RELOC_NUMBERS): Define R_390_IRELATIVE reloc.
2012-06-18 Doug Evans <dje@google.com>
* dwarf2.def (DW_OP): Add DW_OP_GNU_const_index.

View File

@ -119,6 +119,7 @@ START_RELOC_NUMBERS (elf_s390_reloc_type)
RELOC_NUMBER (R_390_GOTPLT20, 59) /* 20 bit offset to jump slot. */
RELOC_NUMBER (R_390_TLS_GOTIE20, 60)/* 20 bit GOT offset for statis TLS
block offset. */
RELOC_NUMBER (R_390_IRELATIVE, 61) /* IFUNC relocation. */
/* These are GNU extensions to enable C++ vtable garbage collection. */
RELOC_NUMBER (R_390_GNU_VTINHERIT, 250)
RELOC_NUMBER (R_390_GNU_VTENTRY, 251)

View File

@ -1,3 +1,8 @@
2012-07-13 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* emulparams/elf_s390.sh (IREL_IN_PLT): Define.
* emulparams/elf64_s390.sh (IREL_IN_PLT): Define.
2012-07-13 Nick Clifton <nickc@redhat.com>
PR ld/14357

View File

@ -12,6 +12,7 @@ TEMPLATE_NAME=elf32
GENERATE_SHLIB_SCRIPT=yes
GENERATE_PIE_SCRIPT=yes
NO_SMALL_DATA=yes
IREL_IN_PLT=
# Treat a host that matches the target with the possible exception of "x"
# in the name as if it were native.

View File

@ -11,3 +11,4 @@ TEMPLATE_NAME=elf32
GENERATE_SHLIB_SCRIPT=yes
GENERATE_PIE_SCRIPT=yes
NO_SMALL_DATA=yes
IREL_IN_PLT=