From 7c8bbca5e670b5ea44b61ff30c5c7fcec47ee405 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sat, 26 Aug 2017 20:26:13 +0930 Subject: [PATCH] PowerPC TPREL reloc handling Tidy how these are handled in PIEs. * elf32-ppc.c (must_be_dyn_reloc): Use bfd_link_dll. Comment. (ppc_elf_check_relocs): Only set DF_STATIC_TLS in shared libs. (ppc_elf_relocate_section): Comment fix. * elf64-ppc.c (must_be_dyn_reloc): Use bfd_link_dll. Comment. (ppc64_elf_check_relocs): Only set DF_STATIC_TLS in shared libs. Support dynamic relocs for TPREL16 when non-pic too. (dec_dynrel_count): Adjust TPREL16 handling as per check_relocs. (ppc64_elf_relocate_section): Support dynamic relocs for TPREL16 when non-pic too. --- bfd/ChangeLog | 12 ++++++++++++ bfd/elf32-ppc.c | 24 +++++++++++++++--------- bfd/elf64-ppc.c | 40 +++++++++++++++++++--------------------- 3 files changed, 46 insertions(+), 30 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index cefe1f1..e785d0e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2017-08-26 Alan Modra + + * elf32-ppc.c (must_be_dyn_reloc): Use bfd_link_dll. Comment. + (ppc_elf_check_relocs): Only set DF_STATIC_TLS in shared libs. + (ppc_elf_relocate_section): Comment fix. + * elf64-ppc.c (must_be_dyn_reloc): Use bfd_link_dll. Comment. + (ppc64_elf_check_relocs): Only set DF_STATIC_TLS in shared libs. + Support dynamic relocs for TPREL16 when non-pic too. + (dec_dynrel_count): Adjust TPREL16 handling as per check_relocs. + (ppc64_elf_relocate_section): Support dynamic relocs for TPREL16 + when non-pic too. + 2017-08-25 H.J. Lu * elf32-i386.c (elf_i386_link_hash_entry): Remove redundant diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index ac3b12b..a5d8193 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -3192,9 +3192,9 @@ struct plt_entry bfd_vma glink_offset; }; -/* Of those relocs that might be copied as dynamic relocs, this function - selects those that must be copied when linking a shared library, - even when the symbol is local. */ +/* Of those relocs that might be copied as dynamic relocs, this + function selects those that must be copied when linking a shared + library or PIE, even when the symbol is local. */ static int must_be_dyn_reloc (struct bfd_link_info *info, @@ -3203,6 +3203,10 @@ must_be_dyn_reloc (struct bfd_link_info *info, switch (r_type) { default: + /* Only relative relocs can be resolved when the object load + address isn't fixed. DTPREL32 is excluded because the + dynamic linker needs to differentiate global dynamic from + local dynamic __tls_index pairs when PPC_OPT_TLS is set. */ return 1; case R_PPC_REL24: @@ -3217,7 +3221,9 @@ must_be_dyn_reloc (struct bfd_link_info *info, case R_PPC_TPREL16_LO: case R_PPC_TPREL16_HI: case R_PPC_TPREL16_HA: - return !bfd_link_executable (info); + /* These relocations are relative but in a shared library the + linker doesn't know the thread pointer base. */ + return bfd_link_dll (info); } } @@ -4151,7 +4157,7 @@ ppc_elf_check_relocs (bfd *abfd, case R_PPC_GOT_TPREL16_LO: case R_PPC_GOT_TPREL16_HI: case R_PPC_GOT_TPREL16_HA: - if (bfd_link_pic (info)) + if (bfd_link_dll (info)) info->flags |= DF_STATIC_TLS; tls_type = TLS_TLS | TLS_TPREL; goto dogottls; @@ -4430,13 +4436,13 @@ ppc_elf_check_relocs (bfd *abfd, return FALSE; break; - /* We shouldn't really be seeing these. */ + /* We shouldn't really be seeing TPREL32. */ case R_PPC_TPREL32: case R_PPC_TPREL16: case R_PPC_TPREL16_LO: case R_PPC_TPREL16_HI: case R_PPC_TPREL16_HA: - if (bfd_link_pic (info)) + if (bfd_link_dll (info)) info->flags |= DF_STATIC_TLS; goto dodyn; @@ -8783,8 +8789,8 @@ ppc_elf_relocate_section (bfd *output_bfd, if (htab->elf.tls_sec != NULL) addend -= htab->elf.tls_sec->vma + TP_OFFSET; /* The TPREL16 relocs shouldn't really be used in shared - libs as they will result in DT_TEXTREL being set, but - support them anyway. */ + libs or with non-local symbols as that will result in + DT_TEXTREL being set, but support them anyway. */ goto dodyn; case R_PPC_TPREL32: diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index f0fde1d..7245038 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -3785,9 +3785,9 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd, calls may use the function descriptor symbol, ie. "bl foo". This behaves exactly as "bl .foo". */ -/* Of those relocs that might be copied as dynamic relocs, this function - selects those that must be copied when linking a shared library, - even when the symbol is local. */ +/* Of those relocs that might be copied as dynamic relocs, this + function selects those that must be copied when linking a shared + library or PIE, even when the symbol is local. */ static int must_be_dyn_reloc (struct bfd_link_info *info, @@ -3796,6 +3796,10 @@ must_be_dyn_reloc (struct bfd_link_info *info, switch (r_type) { default: + /* Only relative relocs can be resolved when the object load + address isn't fixed. DTPREL64 is excluded because the + dynamic linker needs to differentiate global dynamic from + local dynamic __tls_index pairs when PPC64_OPT_TLS is set. */ return 1; case R_PPC64_REL32: @@ -3816,7 +3820,9 @@ must_be_dyn_reloc (struct bfd_link_info *info, case R_PPC64_TPREL16_HIGHEST: case R_PPC64_TPREL16_HIGHESTA: case R_PPC64_TPREL64: - return !bfd_link_executable (info); + /* These relocations are relative but in a shared library the + linker doesn't know the thread pointer base. */ + return bfd_link_dll (info); } } @@ -5496,7 +5502,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_PPC64_GOT_TPREL16_LO_DS: case R_PPC64_GOT_TPREL16_HI: case R_PPC64_GOT_TPREL16_HA: - if (bfd_link_pic (info)) + if (bfd_link_dll (info)) info->flags |= DF_STATIC_TLS; tls_type = TLS_TLS | TLS_TPREL; goto dogottls; @@ -5758,7 +5764,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_PPC64_TPREL64: tls_type = TLS_EXPLICIT | TLS_TLS | TLS_TPREL; - if (bfd_link_pic (info)) + if (bfd_link_dll (info)) info->flags |= DF_STATIC_TLS; goto dotlstoc; @@ -5834,12 +5840,9 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_PPC64_TPREL16_HIGHERA: case R_PPC64_TPREL16_HIGHEST: case R_PPC64_TPREL16_HIGHESTA: - if (bfd_link_pic (info)) - { - info->flags |= DF_STATIC_TLS; - goto dodyn; - } - break; + if (bfd_link_dll (info)) + info->flags |= DF_STATIC_TLS; + goto dodyn; case R_PPC64_ADDR64: if (opd_sym_map != NULL @@ -7798,9 +7801,6 @@ dec_dynrel_count (bfd_vma r_info, case R_PPC64_TPREL16_HIGHERA: case R_PPC64_TPREL16_HIGHEST: case R_PPC64_TPREL16_HIGHESTA: - if (!bfd_link_pic (info)) - return TRUE; - case R_PPC64_TPREL64: case R_PPC64_DTPMOD64: case R_PPC64_DTPREL64: @@ -14882,12 +14882,10 @@ ppc64_elf_relocate_section (bfd *output_bfd, } if (htab->elf.tls_sec != NULL) addend -= htab->elf.tls_sec->vma + TP_OFFSET; - if (bfd_link_pic (info)) - /* The TPREL16 relocs shouldn't really be used in shared - libs as they will result in DT_TEXTREL being set, but - support them anyway. */ - goto dodyn; - break; + /* The TPREL16 relocs shouldn't really be used in shared + libs or with non-local symbols as that will result in + DT_TEXTREL being set, but support them anyway. */ + goto dodyn; case R_PPC64_DTPREL16: case R_PPC64_DTPREL16_LO: -- 2.7.4