From 99ba51255402201c6e193d803ee1f1fc3f2de0e6 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Mon, 19 Oct 2015 15:44:35 +0200 Subject: [PATCH] S/390: ifunc: Redirect local function calls to the IPLT. bfd/ChangeLog: * elf32-s390.c (elf_s390_check_relocs): Set the non_got_ref marker only when linking an executable. (elf_s390_relocate_section): Redirect PC-relative relocs to a IPLT slot. * elf64-s390.c (elf_s390_check_relocs): Set the non_got_ref marker only when linking an executable. (elf_s390_relocate_section): Redirect PC-relative relocs to a IPLT slot. --- bfd/ChangeLog | 11 +++++++++++ bfd/elf32-s390.c | 28 ++++++++++++++++++++++++---- bfd/elf64-s390.c | 24 +++++++++++++++++++----- 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b7f42cd6d3c..3956966a664 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,16 @@ 2015-10-22 Andreas Krebbel + * elf32-s390.c (elf_s390_check_relocs): Set the non_got_ref marker + only when linking an executable. + (elf_s390_relocate_section): Redirect PC-relative relocs to a IPLT + slot. + * elf64-s390.c (elf_s390_check_relocs): Set the non_got_ref marker + only when linking an executable. + (elf_s390_relocate_section): Redirect PC-relative relocs to a IPLT + slot. + +2015-10-22 Andreas Krebbel + * elf32-s390.c (elf_s390_adjust_dynamic_symbol): Set the PLT reference counters for local IFUNC calls. * elf64-s390.c (elf_s390_adjust_dynamic_symbol): Likewise. diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c index d154fb78aff..3fad6b3ccde 100644 --- a/bfd/elf32-s390.c +++ b/bfd/elf32-s390.c @@ -1272,7 +1272,7 @@ elf_s390_check_relocs (bfd *abfd, case R_390_PC24DBL: case R_390_PC32DBL: case R_390_PC32: - if (h != NULL) + if (h != NULL && bfd_link_executable (info)) { /* If this reloc is in a read-only section, we might need a copy reloc. We can't check reliably at this @@ -2776,9 +2776,6 @@ elf_s390_relocate_section (bfd *output_bfd, unresolved_reloc = FALSE; break; - case R_390_8: - case R_390_16: - case R_390_32: case R_390_PC16: case R_390_PC12DBL: case R_390_PC16DBL: @@ -2787,6 +2784,29 @@ elf_s390_relocate_section (bfd *output_bfd, case R_390_PC32: if (h != NULL && s390_is_ifunc_symbol_p (h) + && h->def_regular + && !bfd_link_executable (info)) + { + /* This will not work our if the function does not + happen to set up the GOT pointer for some other + reason. 31 bit PLT entries require r12 to hold the + GOT pointer. + FIXME: Implement an errorcheck. + NOTE: It will work when brasl is not available + (e.g. with -m31 -march=g5) since a local function + call then does use GOTOFF which implies r12 being set + up. */ + relocation = (htab->elf.iplt->output_section->vma + + htab->elf.iplt->output_offset + + h ->plt.offset); + goto do_relocation; + } + + case R_390_8: + case R_390_16: + case R_390_32: + if (h != NULL + && s390_is_ifunc_symbol_p (h) && h->def_regular) { if (!bfd_link_pic (info) || !h->non_got_ref) diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c index 2b6227148d2..bd9c0829e83 100644 --- a/bfd/elf64-s390.c +++ b/bfd/elf64-s390.c @@ -1205,7 +1205,7 @@ elf_s390_check_relocs (bfd *abfd, case R_390_PC32: case R_390_PC32DBL: case R_390_PC64: - if (h != NULL) + if (h != NULL && bfd_link_executable (info)) { /* If this reloc is in a read-only section, we might need a copy reloc. We can't check reliably at this @@ -2718,10 +2718,6 @@ elf_s390_relocate_section (bfd *output_bfd, unresolved_reloc = FALSE; break; - case R_390_8: - case R_390_16: - case R_390_32: - case R_390_64: case R_390_PC16: case R_390_PC12DBL: case R_390_PC16DBL: @@ -2729,6 +2725,24 @@ elf_s390_relocate_section (bfd *output_bfd, case R_390_PC32: case R_390_PC32DBL: case R_390_PC64: + /* The target of these relocs are instruction operands + residing in read-only sections. We cannot emit a runtime + reloc for it. */ + if (h != NULL + && s390_is_ifunc_symbol_p (h) + && h->def_regular + && bfd_link_pic (info)) + { + relocation = (htab->elf.iplt->output_section->vma + + htab->elf.iplt->output_offset + + h->plt.offset); + goto do_relocation; + } + + case R_390_8: + case R_390_16: + case R_390_32: + case R_390_64: if (h != NULL && s390_is_ifunc_symbol_p (h) -- 2.11.4.GIT