From 1bdd8facfbf6f94fa9603f528c7e8bdf91d90bfd Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 18 Sep 2019 10:27:23 +0930 Subject: [PATCH] PowerPC64, support medium model access to common symbols Some versions of clang apparently generate non-PIC on powerpc64le to access common symbols. Since a common symbol and a strong definition with the same name should resolve to the strong definition we have the possibility of non-PIC attempting to access shared library variables. This is really a clanger since powerpc64le is supposed to be PIC by default, but let's see if ld can cope by generating .dynbss copies. * elf64-ppc.c (must_be_dyn_reloc): Return 0 for TOC16 relocs. (ppc64_elf_check_relocs): Support dynamic/copy relocs for TOC16. (ppc64_elf_adjust_dynamic_symbol): Don't keep dynamic reloc when needs_copy even if all relocs are in rw sections. (dec_dynrel_count): Handle TOC16 relocs. (ppc64_elf_relocate_section): Support dynamic relocs for TOC16. (ppc64_elf_finish_dynamic_symbol): Adjust to handle needs_copy semantic change. --- bfd/ChangeLog | 11 +++++++++++ bfd/elf64-ppc.c | 44 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 76939880c79..4f48818ef3e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2019-09-18 Alan Modra + + * elf64-ppc.c (must_be_dyn_reloc): Return 0 for TOC16 relocs. + (ppc64_elf_check_relocs): Support dynamic/copy relocs for TOC16. + (ppc64_elf_adjust_dynamic_symbol): Don't keep dynamic reloc when + needs_copy even if all relocs are in rw sections. + (dec_dynrel_count): Handle TOC16 relocs. + (ppc64_elf_relocate_section): Support dynamic relocs for TOC16. + (ppc64_elf_finish_dynamic_symbol): Adjust to handle needs_copy + semantic change. + 2019-09-16 Phil Blundell * version.m4: Set version to 2.33.50. diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 88ace7e6fe0..345710ee594 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -2745,6 +2745,12 @@ must_be_dyn_reloc (struct bfd_link_info *info, case R_PPC64_REL32: case R_PPC64_REL64: case R_PPC64_REL30: + case R_PPC64_TOC16: + case R_PPC64_TOC16_DS: + case R_PPC64_TOC16_LO: + case R_PPC64_TOC16_HI: + case R_PPC64_TOC16_HA: + case R_PPC64_TOC16_LO_DS: return 0; case R_PPC64_TPREL16: @@ -4830,6 +4836,16 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_PPC64_TOC16_HA: case R_PPC64_TOC16_LO_DS: sec->has_toc_reloc = 1; + if (h != NULL && !bfd_link_pic (info)) + { + /* We may need a copy reloc. */ + h->non_got_ref = 1; + /* Strongly prefer a copy reloc over a dynamic reloc. + glibc ld.so as of 2019-08 will error out if one of + these relocations is emitted. */ + h->needs_copy = 1; + goto dodyn; + } break; /* Marker reloc. */ @@ -6425,7 +6441,9 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info, /* If we don't find any dynamic relocs in read-only sections, then we'll be keeping the dynamic relocs and avoiding the copy reloc. */ - || (ELIMINATE_COPY_RELOCS && !alias_readonly_dynrelocs (h)) + || (ELIMINATE_COPY_RELOCS + && !h->needs_copy + && !alias_readonly_dynrelocs (h)) /* Protected variables do not work with .dynbss. The copy in .dynbss won't be used by the shared library with the protected @@ -6813,6 +6831,16 @@ dec_dynrel_count (bfd_vma r_info, default: return TRUE; + case R_PPC64_TOC16: + case R_PPC64_TOC16_DS: + case R_PPC64_TOC16_LO: + case R_PPC64_TOC16_HI: + case R_PPC64_TOC16_HA: + case R_PPC64_TOC16_LO_DS: + if (h == NULL) + return TRUE; + break; + case R_PPC64_TPREL16: case R_PPC64_TPREL16_LO: case R_PPC64_TPREL16_HI: @@ -15801,6 +15829,8 @@ ppc64_elf_relocate_section (bfd *output_bfd, case R_PPC64_TOC16_LO_DS: case R_PPC64_TOC16_HA: addend -= TOCstart + htab->sec_info[input_section->id].toc_off; + if (h != NULL) + goto dodyn; break; /* Relocate against the beginning of the section. */ @@ -16734,18 +16764,18 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd, break; } - if (h->needs_copy) + if (h->needs_copy + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && (h->root.u.def.section == htab->elf.sdynbss + || h->root.u.def.section == htab->elf.sdynrelro)) { /* This symbol needs a copy reloc. Set it up. */ Elf_Internal_Rela rela; asection *srel; bfd_byte *loc; - if (h->dynindx == -1 - || (h->root.type != bfd_link_hash_defined - && h->root.type != bfd_link_hash_defweak) - || htab->elf.srelbss == NULL - || htab->elf.sreldynrelro == NULL) + if (h->dynindx == -1) abort (); rela.r_offset = (h->root.u.def.value -- 2.30.2