From 46e9995a207140408309dbea40c64f11843db777 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 18 Jul 2019 11:04:06 +0930 Subject: [PATCH] [PowerPC64] Don't store TLS_EXPLICIT in tls_mask This saves a bit in tls_mask, and fixes a bug that could be triggered in the unlikely case that both @got (usual ELF style) and @toc (PowerOpen style) code was used to set up args for __tls_get_addr. * elf64-ppc.c (TLS_EXPLICIT): Define as 256. (ppc64_elf_check_relocs): Don't store TLS_EXPLICIT even if char is more than 8 bits. (ppc64_elf_tls_optimize): Likewise. Make tls_set, tls_clear, and tls_type vars unsigned int. (ppc64_elf_relocate_section): Use r_type rather than TLS_EXPLICIT to select r_type edit. --- bfd/ChangeLog | 10 ++++++++++ bfd/elf64-ppc.c | 17 +++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b913d18d8e8..eb64f86389f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2019-07-18 Alan Modra + + * elf64-ppc.c (TLS_EXPLICIT): Define as 256. + (ppc64_elf_check_relocs): Don't store TLS_EXPLICIT even if char + is more than 8 bits. + (ppc64_elf_tls_optimize): Likewise. Make tls_set, tls_clear, and + tls_type vars unsigned int. + (ppc64_elf_relocate_section): Use r_type rather than TLS_EXPLICIT + to select r_type edit. + 2019-07-18 Alan Modra * elf32-ppc.c (TLS_GDIE): Rename from TLS_TPRELGD throughout file. diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 9c32c692058..0c0d4a4c13e 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -3048,7 +3048,7 @@ struct ppc_link_hash_entry #define TLS_DTPREL 16 /* DTPREL reloc, => LD. */ #define TLS_MARK 32 /* __tls_get_addr call marked. */ #define TLS_GDIE 64 /* GOT TPREL reloc resulting from GD->IE. */ -#define TLS_EXPLICIT 128 /* Marks TOC section TLS relocs. */ +#define TLS_EXPLICIT 256 /* TOC section TLS reloc, not stored. */ unsigned char tls_mask; /* The above field is also used to mark function symbols. In which @@ -4901,7 +4901,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, { struct ppc_link_hash_entry *eh; eh = (struct ppc_link_hash_entry *) h; - eh->tls_mask |= tls_type; + eh->tls_mask |= tls_type & 0xff; } else if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, @@ -7677,7 +7677,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) Elf_Internal_Sym *sym; asection *sym_sec; unsigned char *tls_mask; - unsigned char tls_set, tls_clear, tls_type = 0; + unsigned int tls_set, tls_clear, tls_type = 0; bfd_vma value; bfd_boolean ok_tprel, is_local; long toc_ref_index = 0; @@ -8067,7 +8067,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) } } - *tls_mask |= tls_set; + *tls_mask |= tls_set & 0xff; *tls_mask &= ~tls_clear; } @@ -14530,11 +14530,12 @@ ppc64_elf_relocate_section (bfd *output_bfd, insn2 = 0x7c636a14; /* add 3,3,13 */ if (offset != (bfd_vma) -1) rel[1].r_info = ELF64_R_INFO (STN_UNDEF, R_PPC64_NONE); - if ((tls_mask & TLS_EXPLICIT) == 0) - r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3) - + R_PPC64_GOT_TPREL16_DS); - else + if (r_type == R_PPC64_TOC16 + || r_type == R_PPC64_TOC16_LO) r_type += R_PPC64_TOC16_DS - R_PPC64_TOC16; + else + r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 1)) & 1) + + R_PPC64_GOT_TPREL16_DS); rel->r_info = ELF64_R_INFO (r_symndx, r_type); } else -- 2.30.2