PowerPC64 __tls_get_addr_desc
authorAlan Modra <amodra@gmail.com>
Mon, 20 Jan 2020 02:08:00 +0000 (12:38 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 22 Jan 2020 06:44:08 +0000 (17:14 +1030)
This implements register saving and restoring in the __tls_get_addr
call stub, so that when glibc supports the optimized tls call stub gcc
can generate code that assumes only r0, r12 and of course r3 are
changed on a __tls_get_addr call.  When gcc expects __tls_get_addr
calls to preserve registers the call will be to __tls_get_addr_desc,
which will be translated by the linker to a call to __tls_get_addr_opt.

bfd/
* elf64-ppc.h (struct ppc64_elf_params): Add no_tls_get_addr_regsave.
* elf64-ppc.c (struct ppc_link_hash_table): Add tga_desc and
tga_desc_fd.
(is_tls_get_addr): Match tga_desc and tga_desc_df too.
(STDU_R1_0R1, ADDI_R1_R1): Define.
(tls_get_addr_prologue, tls_get_addr_epilogue): New functions.
(ppc64_elf_tls_setup): Set up tga_desc and tga_desc_fd.  Indirect
tga_desc_fd to opt_fd, and tga_desc to opt.  Set
no_tls_get_addr_regsave.
(branch_reloc_hash_match): Add hash3 and hash4.
(ppc64_elf_tls_optimize): Handle tga_desc_fd and tga_desc too.
(ppc64_elf_size_dynamic_sections): Likewise.
(ppc64_elf_relocate_section): Likewise.
(plt_stub_size, build_plt_stub): Likewise.  Size regsave
__tls_get_addr stub.
(build_tls_get_addr_stub): Build regsave __tls_get_addr stub and
eh_frame.
(ppc_size_one_stub): Handle tga_desc_fd and tga_desc too.  Size
eh_frame for regsave __tls_get_addr.
gas/
* config/tc-ppc.c (parse_tls_arg): Handle tls arg for
__tls_get_addr_desc and __tls_get_addr_opt.
ld/
* emultempl/ppc64elf.em (ppc64_opt, PARSE_AND_LIST_LONGOPTS),
(PARSE_AND_LIST_OPTIONS, PARSE_AND_LIST_ARGS_CASES): Support
--tls-get-addr-regsave and --no-tls-get-addr-regsave.
(params): Init new field.
* ld.texi (--tls-get-addr-regsave, --no-tls-get-addr-regsave):
Document.
* testsuite/ld-powerpc/tlsdesc.s,
* testsuite/ld-powerpc/tlsdesc.d,
* testsuite/ld-powerpc/tlsdesc.wf,
* testsuite/ld-powerpc/tlsdesc2.d,
* testsuite/ld-powerpc/tlsdesc2.wf,
* testsuite/ld-powerpc/tlsexenors.d,
* testsuite/ld-powerpc/tlsexenors.r,
* testsuite/ld-powerpc/tlsexers.d,
* testsuite/ld-powerpc/tlsexers.r,
* testsuite/ld-powerpc/tlsexetocnors.d,
* testsuite/ld-powerpc/tlsexetocrs.d,
* testsuite/ld-powerpc/tlsexetocrs.r,
* testsuite/ld-powerpc/tlsopt6.d,
* testsuite/ld-powerpc/tlsopt6.wf: New.
* testsuite/ld-powerpc/powerpc.exp: Run new tests.

23 files changed:
bfd/ChangeLog
bfd/elf64-ppc.c
bfd/elf64-ppc.h
gas/ChangeLog
gas/config/tc-ppc.c
ld/ChangeLog
ld/emultempl/ppc64elf.em
ld/ld.texi
ld/testsuite/ld-powerpc/powerpc.exp
ld/testsuite/ld-powerpc/tlsdesc.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/tlsdesc.s [new file with mode: 0644]
ld/testsuite/ld-powerpc/tlsdesc.wf [new file with mode: 0644]
ld/testsuite/ld-powerpc/tlsdesc2.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/tlsdesc2.wf [new file with mode: 0644]
ld/testsuite/ld-powerpc/tlsexenors.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/tlsexenors.r [new file with mode: 0644]
ld/testsuite/ld-powerpc/tlsexers.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/tlsexers.r [new file with mode: 0644]
ld/testsuite/ld-powerpc/tlsexetocnors.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/tlsexetocrs.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/tlsexetocrs.r [new file with mode: 0644]
ld/testsuite/ld-powerpc/tlsopt6.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/tlsopt6.wf [new file with mode: 0644]

index 894faec848de7184e91388f22469d1171c7f3466..1bd9b5f979a1a91f3bc8c9ead32d361baf38a8e2 100644 (file)
@@ -1,3 +1,25 @@
+2020-01-22  Alan Modra  <amodra@gmail.com>
+
+       * elf64-ppc.h (struct ppc64_elf_params): Add no_tls_get_addr_regsave.
+       * elf64-ppc.c (struct ppc_link_hash_table): Add tga_desc and
+       tga_desc_fd.
+       (is_tls_get_addr): Match tga_desc and tga_desc_df too.
+       (STDU_R1_0R1, ADDI_R1_R1): Define.
+       (tls_get_addr_prologue, tls_get_addr_epilogue): New functions.
+       (ppc64_elf_tls_setup): Set up tga_desc and tga_desc_fd.  Indirect
+       tga_desc_fd to opt_fd, and tga_desc to opt.  Set
+       no_tls_get_addr_regsave.
+       (branch_reloc_hash_match): Add hash3 and hash4.
+       (ppc64_elf_tls_optimize): Handle tga_desc_fd and tga_desc too.
+       (ppc64_elf_size_dynamic_sections): Likewise.
+       (ppc64_elf_relocate_section): Likewise.
+       (plt_stub_size, build_plt_stub): Likewise.  Size regsave
+       __tls_get_addr stub.
+       (build_tls_get_addr_stub): Build regsave __tls_get_addr stub and
+       eh_frame.
+       (ppc_size_one_stub): Handle tga_desc_fd and tga_desc too.  Size
+       eh_frame for regsave __tls_get_addr.
+
 2020-01-22  Alan Modra  <amodra@gmail.com>
 
        * elf64-ppc.c (ppc64_elf_size_stubs): Correct condition under
index 2ee9fe404cb8b68e184eaab56a79934990234a44..6b11a11018d0e30bd8c3dc626dbde917a14b28d8 100644 (file)
@@ -3180,6 +3180,8 @@ struct ppc_link_hash_table
   /* Shortcut to .__tls_get_addr and __tls_get_addr.  */
   struct ppc_link_hash_entry *tls_get_addr;
   struct ppc_link_hash_entry *tls_get_addr_fd;
+  struct ppc_link_hash_entry *tga_desc;
+  struct ppc_link_hash_entry *tga_desc_fd;
 
   /* The size of reliplt used by got entry relocs.  */
   bfd_size_type got_reli_size;
@@ -5600,8 +5602,8 @@ static bfd_boolean
 is_tls_get_addr (struct elf_link_hash_entry *h,
                 struct ppc_link_hash_table *htab)
 {
-  return (h == &htab->tls_get_addr_fd->elf
-         || h == &htab->tls_get_addr->elf);
+  return (h == &htab->tls_get_addr_fd->elf || h == &htab->tga_desc_fd->elf
+         || h == &htab->tls_get_addr->elf || h == &htab->tga_desc->elf);
 }
 
 static bfd_boolean func_desc_adjust (struct elf_link_hash_entry *, void *);
@@ -6078,6 +6080,84 @@ restvr_tail (bfd *abfd, bfd_byte *p, int r)
   return p + 4;
 }
 
+#define STDU_R1_0R1    0xf8210001
+#define ADDI_R1_R1     0x38210000
+
+/* Emit prologue of wrapper preserving regs around a call to
+   __tls_get_addr_opt.  */
+
+static bfd_byte *
+tls_get_addr_prologue (bfd *obfd, bfd_byte *p, struct ppc_link_hash_table *htab)
+{
+  unsigned int i;
+
+  bfd_put_32 (obfd, MFLR_R0, p);
+  p += 4;
+  bfd_put_32 (obfd, STD_R0_0R1 + 16, p);
+  p += 4;
+
+  if (htab->opd_abi)
+    {
+      for (i = 4; i < 12; i++)
+       {
+         bfd_put_32 (obfd,
+                     STD_R0_0R1 | i << 21 | (-(13 - i) * 8 & 0xffff), p);
+         p += 4;
+       }
+      bfd_put_32 (obfd, STDU_R1_0R1 | (-128 & 0xffff), p);
+      p += 4;
+    }
+  else
+    {
+      for (i = 4; i < 12; i++)
+       {
+         bfd_put_32 (obfd,
+                     STD_R0_0R1 | i << 21 | (-(12 - i) * 8 & 0xffff), p);
+         p += 4;
+       }
+      bfd_put_32 (obfd, STDU_R1_0R1 | (-96 & 0xffff), p);
+      p += 4;
+    }
+  return p;
+}
+
+/* Emit epilogue of wrapper preserving regs around a call to
+   __tls_get_addr_opt.  */
+
+static bfd_byte *
+tls_get_addr_epilogue (bfd *obfd, bfd_byte *p, struct ppc_link_hash_table *htab)
+{
+  unsigned int i;
+
+  if (htab->opd_abi)
+    {
+      for (i = 4; i < 12; i++)
+       {
+         bfd_put_32 (obfd, LD_R0_0R1 | i << 21 | (128 - (13 - i) * 8), p);
+         p += 4;
+       }
+      bfd_put_32 (obfd, ADDI_R1_R1 | 128, p);
+      p += 4;
+    }
+  else
+    {
+      for (i = 4; i < 12; i++)
+       {
+         bfd_put_32 (obfd, LD_R0_0R1 | i << 21 | (96 - (12 - i) * 8), p);
+         p += 4;
+       }
+      bfd_put_32 (obfd, ADDI_R1_R1 | 96, p);
+      p += 4;
+    }
+  bfd_put_32 (obfd, LD_R0_0R1 | 16, p);
+  p += 4;
+  bfd_put_32 (obfd, MTLR_R0, p);
+  p += 4;
+  bfd_put_32 (obfd, BLR, p);
+  p += 4;
+  return p;
+}
+
 /* Called via elf_link_hash_traverse to transfer dynamic linking
    information on function code symbol entries to their corresponding
    function descriptor symbol entries.  */
@@ -7592,6 +7672,7 @@ asection *
 ppc64_elf_tls_setup (struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab;
+  struct elf_link_hash_entry *tga, *tga_fd, *desc, *desc_fd;
 
   htab = ppc_hash_table (info);
   if (htab == NULL)
@@ -7628,18 +7709,29 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
       (_("warning: --plt-localentry is especially dangerous without "
         "ld.so support to detect ABI violations"));
 
-  htab->tls_get_addr = ((struct ppc_link_hash_entry *)
-                       elf_link_hash_lookup (&htab->elf, ".__tls_get_addr",
-                                             FALSE, FALSE, TRUE));
+  tga = elf_link_hash_lookup (&htab->elf, ".__tls_get_addr",
+                             FALSE, FALSE, TRUE);
+  htab->tls_get_addr = ppc_elf_hash_entry (tga);
+
   /* Move dynamic linking info to the function descriptor sym.  */
-  if (htab->tls_get_addr != NULL)
-    func_desc_adjust (&htab->tls_get_addr->elf, info);
-  htab->tls_get_addr_fd = ((struct ppc_link_hash_entry *)
-                          elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
-                                                FALSE, FALSE, TRUE));
+  if (tga != NULL)
+    func_desc_adjust (tga, info);
+  tga_fd = elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
+                                FALSE, FALSE, TRUE);
+  htab->tls_get_addr_fd = ppc_elf_hash_entry (tga_fd);
+
+  desc = elf_link_hash_lookup (&htab->elf, ".__tls_get_addr_desc",
+                              FALSE, FALSE, TRUE);
+  htab->tga_desc = ppc_elf_hash_entry (desc);
+  if (desc != NULL)
+    func_desc_adjust (desc, info);
+  desc_fd = elf_link_hash_lookup (&htab->elf, "__tls_get_addr_desc",
+                                 FALSE, FALSE, TRUE);
+  htab->tga_desc_fd = ppc_elf_hash_entry (desc_fd);
+
   if (htab->params->tls_get_addr_opt)
     {
-      struct elf_link_hash_entry *opt, *opt_fd, *tga, *tga_fd;
+      struct elf_link_hash_entry *opt, *opt_fd;
 
       opt = elf_link_hash_lookup (&htab->elf, ".__tls_get_addr_opt",
                                  FALSE, FALSE, TRUE);
@@ -7655,24 +7747,49 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
             signalled by the presence of __tls_get_addr_opt, and we'll
             be calling __tls_get_addr via a plt call stub, then
             make __tls_get_addr point to __tls_get_addr_opt.  */
-         tga_fd = &htab->tls_get_addr_fd->elf;
-         if (htab->elf.dynamic_sections_created
-             && tga_fd != NULL
-             && (tga_fd->type == STT_FUNC
-                 || tga_fd->needs_plt)
-             && !(SYMBOL_CALLS_LOCAL (info, tga_fd)
-                  || UNDEFWEAK_NO_DYNAMIC_RELOC (info, tga_fd)))
+         if (!(htab->elf.dynamic_sections_created
+               && tga_fd != NULL
+               && (tga_fd->type == STT_FUNC
+                   || tga_fd->needs_plt)
+               && !(SYMBOL_CALLS_LOCAL (info, tga_fd)
+                    || UNDEFWEAK_NO_DYNAMIC_RELOC (info, tga_fd))))
+           tga_fd = NULL;
+         if (!(htab->elf.dynamic_sections_created
+               && desc_fd != NULL
+               && (desc_fd->type == STT_FUNC
+                   || desc_fd->needs_plt)
+               && !(SYMBOL_CALLS_LOCAL (info, desc_fd)
+                    || UNDEFWEAK_NO_DYNAMIC_RELOC (info, desc_fd))))
+           desc_fd = NULL;
+
+         if (tga_fd != NULL || desc_fd != NULL)
            {
-             struct plt_entry *ent;
+             struct plt_entry *ent = NULL;
 
-             for (ent = tga_fd->plt.plist; ent != NULL; ent = ent->next)
-               if (ent->plt.refcount > 0)
-                 break;
+             if (tga_fd != NULL)
+               for (ent = tga_fd->plt.plist; ent != NULL; ent = ent->next)
+                 if (ent->plt.refcount > 0)
+                   break;
+             if (ent == NULL && desc_fd != NULL)
+               for (ent = desc_fd->plt.plist; ent != NULL; ent = ent->next)
+                 if (ent->plt.refcount > 0)
+                   break;
              if (ent != NULL)
                {
-                 tga_fd->root.type = bfd_link_hash_indirect;
-                 tga_fd->root.u.i.link = &opt_fd->root;
-                 ppc64_elf_copy_indirect_symbol (info, opt_fd, tga_fd);
+                 if (tga_fd != NULL)
+                   {
+                     tga_fd->root.type = bfd_link_hash_indirect;
+                     tga_fd->root.u.i.link = &opt_fd->root;
+                     tga_fd->root.u.i.warning = NULL;
+                     ppc64_elf_copy_indirect_symbol (info, opt_fd, tga_fd);
+                   }
+                 if (desc_fd != NULL)
+                   {
+                     desc_fd->root.type = bfd_link_hash_indirect;
+                     desc_fd->root.u.i.link = &opt_fd->root;
+                     desc_fd->root.u.i.warning = NULL;
+                     ppc64_elf_copy_indirect_symbol (info, opt_fd, desc_fd);
+                   }
                  opt_fd->mark = 1;
                  if (opt_fd->dynindx != -1)
                    {
@@ -7683,24 +7800,50 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
                      if (!bfd_elf_link_record_dynamic_symbol (info, opt_fd))
                        return NULL;
                    }
-                 htab->tls_get_addr_fd = ppc_elf_hash_entry (opt_fd);
-                 tga = &htab->tls_get_addr->elf;
-                 if (opt != NULL && tga != NULL)
+                 if (tga_fd != NULL)
                    {
-                     tga->root.type = bfd_link_hash_indirect;
-                     tga->root.u.i.link = &opt->root;
-                     ppc64_elf_copy_indirect_symbol (info, opt, tga);
-                     opt->mark = 1;
-                     _bfd_elf_link_hash_hide_symbol (info, opt,
-                                                     tga->forced_local);
-                     htab->tls_get_addr = ppc_elf_hash_entry (opt);
+                     htab->tls_get_addr_fd = ppc_elf_hash_entry (opt_fd);
+                     tga = &htab->tls_get_addr->elf;
+                     if (opt != NULL && tga != NULL)
+                       {
+                         tga->root.type = bfd_link_hash_indirect;
+                         tga->root.u.i.link = &opt->root;
+                         tga->root.u.i.warning = NULL;
+                         ppc64_elf_copy_indirect_symbol (info, opt, tga);
+                         opt->mark = 1;
+                         _bfd_elf_link_hash_hide_symbol (info, opt,
+                                                         tga->forced_local);
+                         htab->tls_get_addr = ppc_elf_hash_entry (opt);
+                       }
+                     htab->tls_get_addr_fd->oh = htab->tls_get_addr;
+                     htab->tls_get_addr_fd->is_func_descriptor = 1;
+                     if (htab->tls_get_addr != NULL)
+                       {
+                         htab->tls_get_addr->oh = htab->tls_get_addr_fd;
+                         htab->tls_get_addr->is_func = 1;
+                       }
                    }
-                 htab->tls_get_addr_fd->oh = htab->tls_get_addr;
-                 htab->tls_get_addr_fd->is_func_descriptor = 1;
-                 if (htab->tls_get_addr != NULL)
+                 if (desc_fd != NULL)
                    {
-                     htab->tls_get_addr->oh = htab->tls_get_addr_fd;
-                     htab->tls_get_addr->is_func = 1;
+                     htab->tga_desc_fd = ppc_elf_hash_entry (opt_fd);
+                     if (opt != NULL && desc != NULL)
+                       {
+                         desc->root.type = bfd_link_hash_indirect;
+                         desc->root.u.i.link = &opt->root;
+                         desc->root.u.i.warning = NULL;
+                         ppc64_elf_copy_indirect_symbol (info, opt, desc);
+                         opt->mark = 1;
+                         _bfd_elf_link_hash_hide_symbol (info, opt,
+                                                         desc->forced_local);
+                         htab->tga_desc = ppc_elf_hash_entry (opt);
+                       }
+                     htab->tga_desc_fd->oh = htab->tga_desc;
+                     htab->tga_desc_fd->is_func_descriptor = 1;
+                     if (htab->tga_desc != NULL)
+                       {
+                         htab->tga_desc->oh = htab->tga_desc_fd;
+                         htab->tga_desc->is_func = 1;
+                       }
                    }
                }
            }
@@ -7708,17 +7851,25 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
       else if (htab->params->tls_get_addr_opt < 0)
        htab->params->tls_get_addr_opt = 0;
     }
+
+  if (htab->tga_desc_fd != NULL
+      && htab->params->tls_get_addr_opt
+      && htab->params->no_tls_get_addr_regsave == -1)
+    htab->params->no_tls_get_addr_regsave = 0;
+
   return _bfd_elf_tls_setup (info->output_bfd, info);
 }
 
 /* Return TRUE iff REL is a branch reloc with a global symbol matching
-   HASH1 or HASH2.  */
+   any of HASH1, HASH2, HASH3, or HASH4.  */
 
 static bfd_boolean
 branch_reloc_hash_match (const bfd *ibfd,
                         const Elf_Internal_Rela *rel,
                         const struct ppc_link_hash_entry *hash1,
-                        const struct ppc_link_hash_entry *hash2)
+                        const struct ppc_link_hash_entry *hash2,
+                        const struct ppc_link_hash_entry *hash3,
+                        const struct ppc_link_hash_entry *hash4)
 {
   Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (ibfd);
   enum elf_ppc64_reloc_type r_type = ELF64_R_TYPE (rel->r_info);
@@ -7731,7 +7882,8 @@ branch_reloc_hash_match (const bfd *ibfd,
 
       h = sym_hashes[r_symndx - symtab_hdr->sh_info];
       h = elf_follow_link (h);
-      if (h == &hash1->elf || h == &hash2->elf)
+      if (h == &hash1->elf || h == &hash2->elf
+         || h == &hash3->elf || h == &hash4->elf)
        return TRUE;
     }
   return FALSE;
@@ -8078,8 +8230,10 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
 
                      if (rel + 1 < relend
                          && branch_reloc_hash_match (ibfd, rel + 1,
+                                                     htab->tls_get_addr_fd,
+                                                     htab->tga_desc_fd,
                                                      htab->tls_get_addr,
-                                                     htab->tls_get_addr_fd))
+                                                     htab->tga_desc))
                        {
                          if (expecting_tls_get_addr == 2)
                            {
@@ -8134,15 +8288,29 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                    {
                      struct plt_entry *ent = NULL;
 
-                     if (htab->tls_get_addr != NULL)
+                     if (htab->tls_get_addr_fd != NULL)
+                       for (ent = htab->tls_get_addr_fd->elf.plt.plist;
+                            ent != NULL;
+                            ent = ent->next)
+                         if (ent->addend == 0)
+                           break;
+
+                     if (ent == NULL && htab->tga_desc_fd != NULL)
+                       for (ent = htab->tga_desc_fd->elf.plt.plist;
+                            ent != NULL;
+                            ent = ent->next)
+                         if (ent->addend == 0)
+                           break;
+
+                     if (ent == NULL && htab->tls_get_addr != NULL)
                        for (ent = htab->tls_get_addr->elf.plt.plist;
                             ent != NULL;
                             ent = ent->next)
                          if (ent->addend == 0)
                            break;
 
-                     if (ent == NULL && htab->tls_get_addr_fd != NULL)
-                       for (ent = htab->tls_get_addr_fd->elf.plt.plist;
+                     if (ent == NULL && htab->tga_desc != NULL)
+                       for (ent = htab->tga_desc->elf.plt.plist;
                             ent != NULL;
                             ent = ent->next)
                          if (ent->addend == 0)
@@ -10088,8 +10256,10 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
        }
 
       tls_opt = (htab->params->tls_get_addr_opt
-                && htab->tls_get_addr_fd != NULL
-                && htab->tls_get_addr_fd->elf.plt.plist != NULL);
+                && ((htab->tls_get_addr_fd != NULL
+                     && htab->tls_get_addr_fd->elf.plt.plist != NULL)
+                    || (htab->tga_desc_fd != NULL
+                        && htab->tga_desc_fd->elf.plt.plist != NULL)));
       if (tls_opt || !htab->opd_abi)
        {
          if (!add_dynamic_entry (DT_PPC64_OPT, tls_opt ? PPC64_OPT_TLS : 0))
@@ -10668,9 +10838,18 @@ plt_stub_size (struct ppc_link_hash_table *htab,
       && is_tls_get_addr (&stub_entry->h->elf, htab)
       && htab->params->tls_get_addr_opt)
     {
-      size += 7 * 4;
-      if (stub_entry->stub_type == ppc_stub_plt_call_r2save)
-       size += 6 * 4;
+      if (htab->params->no_tls_get_addr_regsave)
+       {
+         size += 7 * 4;
+         if (stub_entry->stub_type == ppc_stub_plt_call_r2save)
+           size += 6 * 4;
+       }
+      else
+       {
+         size += 30 * 4;
+         if (stub_entry->stub_type == ppc_stub_plt_call_r2save)
+           size += 4;
+       }
     }
   return size;
 }
@@ -10901,6 +11080,7 @@ build_tls_get_addr_stub (struct ppc_link_hash_table *htab,
 {
   bfd *obfd = htab->params->stub_bfd;
   bfd_byte *loc = p;
+  unsigned int i;
 
   bfd_put_32 (obfd, LD_R0_0R3 + 0, p),         p += 4;
   bfd_put_32 (obfd, LD_R12_0R3 + 8, p),                p += 4;
@@ -10909,40 +11089,112 @@ build_tls_get_addr_stub (struct ppc_link_hash_table *htab,
   bfd_put_32 (obfd, ADD_R3_R12_R13, p),                p += 4;
   bfd_put_32 (obfd, BEQLR, p),                 p += 4;
   bfd_put_32 (obfd, MR_R3_R0, p),              p += 4;
-  if (r != NULL)
-    r[0].r_offset += 7 * 4;
-  if (stub_entry->stub_type != ppc_stub_plt_call_r2save)
-    return build_plt_stub (htab, stub_entry, p, offset, r);
+  if (htab->params->no_tls_get_addr_regsave)
+    {
+      if (r != NULL)
+       r[0].r_offset += 7 * 4;
+      if (stub_entry->stub_type != ppc_stub_plt_call_r2save)
+       return build_plt_stub (htab, stub_entry, p, offset, r);
 
-  bfd_put_32 (obfd, MFLR_R0, p),               p += 4;
-  bfd_put_32 (obfd, STD_R0_0R1 + STK_LINKER (htab), p), p += 4;
+      bfd_put_32 (obfd, MFLR_R0, p);
+      p += 4;
+      bfd_put_32 (obfd, STD_R0_0R1 + STK_LINKER (htab), p);
+      p += 4;
 
-  if (r != NULL)
-    r[0].r_offset += 2 * 4;
-  p = build_plt_stub (htab, stub_entry, p, offset, r);
-  bfd_put_32 (obfd, BCTRL, p - 4);
+      if (r != NULL)
+       r[0].r_offset += 2 * 4;
+      p = build_plt_stub (htab, stub_entry, p, offset, r);
+      bfd_put_32 (obfd, BCTRL, p - 4);
 
-  bfd_put_32 (obfd, LD_R2_0R1 + STK_TOC (htab), p),    p += 4;
-  bfd_put_32 (obfd, LD_R0_0R1 + STK_LINKER (htab), p), p += 4;
-  bfd_put_32 (obfd, MTLR_R0, p),               p += 4;
-  bfd_put_32 (obfd, BLR, p),                   p += 4;
+      bfd_put_32 (obfd, LD_R2_0R1 + STK_TOC (htab), p);
+      p += 4;
+      bfd_put_32 (obfd, LD_R0_0R1 + STK_LINKER (htab), p);
+      p += 4;
+      bfd_put_32 (obfd, MTLR_R0, p);
+      p += 4;
+      bfd_put_32 (obfd, BLR, p);
+      p += 4;
+    }
+  else
+    {
+      p = tls_get_addr_prologue (obfd, p, htab);
+
+      if (r != NULL)
+       r[0].r_offset += 18 * 4;
+
+      p = build_plt_stub (htab, stub_entry, p, offset, r);
+      bfd_put_32 (obfd, BCTRL, p - 4);
+
+      if (stub_entry->stub_type == ppc_stub_plt_call_r2save)
+       {
+         bfd_put_32 (obfd, LD_R2_0R1 + STK_TOC (htab), p);
+         p += 4;
+       }
+
+      p = tls_get_addr_epilogue (obfd, p, htab);
+    }
 
   if (htab->glink_eh_frame != NULL
       && htab->glink_eh_frame->size != 0)
     {
       bfd_byte *base, *eh;
-      unsigned int lr_used, delta;
 
       base = htab->glink_eh_frame->contents + stub_entry->group->eh_base + 17;
       eh = base + stub_entry->group->eh_size;
-      lr_used = stub_entry->stub_offset + (p - 20 - loc);
-      delta = lr_used - stub_entry->group->lr_restore;
-      stub_entry->group->lr_restore = lr_used + 16;
-      eh = eh_advance (htab->elf.dynobj, eh, delta);
-      *eh++ = DW_CFA_offset_extended_sf;
-      *eh++ = 65;
-      *eh++ = -(STK_LINKER (htab) / 8) & 0x7f;
-      *eh++ = DW_CFA_advance_loc + 4;
+      if (htab->params->no_tls_get_addr_regsave)
+       {
+         unsigned int lr_used, delta;
+         lr_used = stub_entry->stub_offset + (p - 20 - loc);
+         delta = lr_used - stub_entry->group->lr_restore;
+         stub_entry->group->lr_restore = lr_used + 16;
+         eh = eh_advance (htab->elf.dynobj, eh, delta);
+         *eh++ = DW_CFA_offset_extended_sf;
+         *eh++ = 65;
+         *eh++ = -(STK_LINKER (htab) / 8) & 0x7f;
+         *eh++ = DW_CFA_advance_loc + 4;
+       }
+      else
+       {
+         unsigned int cfa_updt, delta;
+         /* After the bctrl, lr has been modified so we need to emit
+            .eh_frame info saying the return address is on the stack.  In
+            fact we must put the EH info at or before the call rather
+            than after it, because the EH info for a call needs to be
+            specified by that point.
+            See libgcc/unwind-dw2.c execute_cfa_program.
+            Any stack pointer update must be described immediately after
+            the instruction making the change, and since the stdu occurs
+            after saving regs we put all the reg saves and the cfa
+            change there.  */
+         cfa_updt = stub_entry->stub_offset + 18 * 4;
+         delta = cfa_updt - stub_entry->group->lr_restore;
+         stub_entry->group->lr_restore
+           = stub_entry->stub_offset + (p - loc) - 4;
+         eh = eh_advance (htab->elf.dynobj, eh, delta);
+         *eh++ = DW_CFA_def_cfa_offset;
+         if (htab->opd_abi)
+           {
+             *eh++ = 128;
+             *eh++ = 1;
+           }
+         else
+           *eh++ = 96;
+         *eh++ = DW_CFA_offset_extended_sf;
+         *eh++ = 65;
+         *eh++ = (-16 / 8) & 0x7f;
+         for (i = 4; i < 12; i++)
+           {
+             *eh++ = DW_CFA_offset + i;
+             *eh++ = (htab->opd_abi ? 13 : 12) - i;
+           }
+         *eh++ = (DW_CFA_advance_loc
+                  + (stub_entry->group->lr_restore - 8 - cfa_updt) / 4);
+         *eh++ = DW_CFA_def_cfa_offset;
+         *eh++ = 0;
+         for (i = 4; i < 12; i++)
+           *eh++ = DW_CFA_restore + i;
+         *eh++ = DW_CFA_advance_loc + 2;
+       }
       *eh++ = DW_CFA_restore_extended;
       *eh++ = 65;
       stub_entry->group->eh_size = eh - base;
@@ -11920,19 +12172,23 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
          && htab->params->tls_get_addr_opt
          && stub_entry->stub_type == ppc_stub_plt_call_r2save)
        {
-         /* After the bctrl, lr has been modified so we need to
-            emit .eh_frame info saying the return address is
-            on the stack.  In fact we put the EH info specifying
-            that the return address is on the stack *at* the
-            call rather than after it, because the EH info for a
-            call needs to be specified by that point.
-            See libgcc/unwind-dw2.c execute_cfa_program.  */
-         lr_used = stub_entry->stub_offset + size - 20;
-         /* The eh_frame info will consist of a DW_CFA_advance_loc
-            or variant, DW_CFA_offset_externed_sf, 65, -stackoff,
-            DW_CFA_advance_loc+4, DW_CFA_restore_extended, 65.  */
-         delta = lr_used - stub_entry->group->lr_restore;
-         stub_entry->group->eh_size += eh_advance_size (delta) + 6;
+         if (htab->params->no_tls_get_addr_regsave)
+           {
+             lr_used = stub_entry->stub_offset + size - 20;
+             /* The eh_frame info will consist of a DW_CFA_advance_loc
+                or variant, DW_CFA_offset_externed_sf, 65, -stackoff,
+                DW_CFA_advance_loc+4, DW_CFA_restore_extended, 65.  */
+             delta = lr_used - stub_entry->group->lr_restore;
+             stub_entry->group->eh_size += eh_advance_size (delta) + 6;
+           }
+         else
+           {
+             /* Adjustments to r1 need to be described.  */
+             unsigned int cfa_updt = stub_entry->stub_offset + 18 * 4;
+             delta = cfa_updt - stub_entry->group->lr_restore;
+             stub_entry->group->eh_size += eh_advance_size (delta);
+             stub_entry->group->eh_size += htab->opd_abi ? 36 : 35;
+           }
          stub_entry->group->lr_restore = size - 4;
        }
       break;
@@ -14756,8 +15012,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              if (input_section->nomark_tls_get_addr
                  && rel + 1 < relend
                  && branch_reloc_hash_match (input_bfd, rel + 1,
+                                             htab->tls_get_addr_fd,
+                                             htab->tga_desc_fd,
                                              htab->tls_get_addr,
-                                             htab->tls_get_addr_fd))
+                                             htab->tga_desc))
                offset = rel[1].r_offset;
              /* We read the low GOT_TLS (or TOC16) insn because we
                 need to keep the destination reg.  It may be
index bc7181fe5eeaa5437e61f1c0b11e4ebbede6062d..a2ffd4eb72ef56db0aa87d7dd37751dbee2fbf08 100644 (file)
@@ -36,6 +36,9 @@ struct ppc64_elf_params
   /* Whether to use a special call stub for __tls_get_addr.  */
   int tls_get_addr_opt;
 
+  /* Whether the special call stub should save r4..r12.  */
+  int no_tls_get_addr_regsave;
+
   /* Whether to allow multiple toc sections.  */
   int no_multi_toc;
 
index 8f414396f5994e578954a0b6aeeb5404a1bc240d..2d247a101279948a7f2b66bc80085f53460418bf 100644 (file)
@@ -1,3 +1,8 @@
+2020-01-22  Alan Modra  <amodra@gmail.com>
+
+       * config/tc-ppc.c (parse_tls_arg): Handle tls arg for
+       __tls_get_addr_desc and __tls_get_addr_opt.
+
 2020-01-21  Jan Beulich  <jbeulich@suse.com>
 
        * testsuite/gas/i386/inval-crc32.s,
index 896b6b345635c2dcb34ed24165e7d251b6b6f240..0b24298c2bbdce7e6cb6f8f97851d1bd8b2fe409 100644 (file)
@@ -3255,7 +3255,10 @@ parse_tls_arg (char **str, const expressionS *exp, struct ppc_fixup *tls_fix)
     ++sym_name;
 
   tls_fix->reloc = BFD_RELOC_NONE;
-  if (strcasecmp (sym_name, "__tls_get_addr") == 0)
+  if (strncasecmp (sym_name, "__tls_get_addr", 14) == 0
+      && (sym_name[14] == 0
+         || strcasecmp (sym_name + 14, "_desc") == 0
+         || strcasecmp (sym_name + 14, "_opt") == 0))
     {
       char *hold = input_line_pointer;
       input_line_pointer = *str + 1;
index d8949bbc387e63585fc14db9ae7a1b3538c81c9e..edfc0903921aba5e465f3726e4be236501b195ac 100644 (file)
@@ -1,3 +1,27 @@
+2020-01-22  Alan Modra  <amodra@gmail.com>
+
+       * emultempl/ppc64elf.em (ppc64_opt, PARSE_AND_LIST_LONGOPTS),
+       (PARSE_AND_LIST_OPTIONS, PARSE_AND_LIST_ARGS_CASES): Support
+       --tls-get-addr-regsave and --no-tls-get-addr-regsave.
+       (params): Init new field.
+       * ld.texi (--tls-get-addr-regsave, --no-tls-get-addr-regsave):
+       Document.
+       * testsuite/ld-powerpc/tlsdesc.s,
+       * testsuite/ld-powerpc/tlsdesc.d,
+       * testsuite/ld-powerpc/tlsdesc.wf,
+       * testsuite/ld-powerpc/tlsdesc2.d,
+       * testsuite/ld-powerpc/tlsdesc2.wf,
+       * testsuite/ld-powerpc/tlsexenors.d,
+       * testsuite/ld-powerpc/tlsexenors.r,
+       * testsuite/ld-powerpc/tlsexers.d,
+       * testsuite/ld-powerpc/tlsexers.r,
+       * testsuite/ld-powerpc/tlsexetocnors.d,
+       * testsuite/ld-powerpc/tlsexetocrs.d,
+       * testsuite/ld-powerpc/tlsexetocrs.r,
+       * testsuite/ld-powerpc/tlsopt6.d,
+       * testsuite/ld-powerpc/tlsopt6.wf: New.
+       * testsuite/ld-powerpc/powerpc.exp: Run new tests.
+
 2020-01-22  Yuri Chornoivan  <yurchor@mageia.org>
 
        PR 25417
index caa4f820837390eb828aa5ad338f8e0b460bface..6633f8156acf2dd135032e8b01ae2bd45ba59261 100644 (file)
@@ -36,7 +36,7 @@ static void ppc_layout_sections_again (void);
 static struct ppc64_elf_params params = { NULL,
                                          &ppc_add_stub_section,
                                          &ppc_layout_sections_again,
-                                         1, -1, 0,
+                                         1, -1, -1, 0,
                                          ${DEFAULT_PLT_STATIC_CHAIN-0}, -1, 5,
                                          -1, 0, -1, -1, 0};
 
@@ -694,6 +694,8 @@ enum ppc64_opt
   OPTION_NO_TLS_OPT,
   OPTION_TLS_GET_ADDR_OPT,
   OPTION_NO_TLS_GET_ADDR_OPT,
+  OPTION_TLS_GET_ADDR_REGSAVE,
+  OPTION_NO_TLS_GET_ADDR_REGSAVE,
   OPTION_NO_OPD_OPT,
   OPTION_NO_INLINE_OPT,
   OPTION_NO_TOC_OPT,
@@ -722,6 +724,8 @@ PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}'
   { "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT },
   { "tls-get-addr-optimize", no_argument, NULL, OPTION_TLS_GET_ADDR_OPT },
   { "no-tls-get-addr-optimize", no_argument, NULL, OPTION_NO_TLS_GET_ADDR_OPT },
+  { "tls-get-addr-regsave", no_argument, NULL, OPTION_TLS_GET_ADDR_REGSAVE },
+  { "no-tls-get-addr-regsave", no_argument, NULL, OPTION_NO_TLS_GET_ADDR_REGSAVE},
   { "no-opd-optimize", no_argument, NULL, OPTION_NO_OPD_OPT },
   { "no-inline-optimize", no_argument, NULL, OPTION_NO_INLINE_OPT },
   { "no-toc-optimize", no_argument, NULL, OPTION_NO_TOC_OPT },
@@ -798,6 +802,12 @@ PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'
   --no-tls-get-addr-optimize  Don'\''t use a special __tls_get_addr call\n"
                   ));
   fprintf (file, _("\
+  --tls-get-addr-regsave      Force register save __tls_get_addr stub\n"
+                  ));
+  fprintf (file, _("\
+  --no-tls-get-addr-regsave   Don'\''t use register save __tls_get_addr stub\n"
+                  ));
+  fprintf (file, _("\
   --no-opd-optimize           Don'\''t optimize the OPD section\n"
                   ));
   fprintf (file, _("\
@@ -905,6 +915,14 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
       params.tls_get_addr_opt = 0;
       break;
 
+    case OPTION_TLS_GET_ADDR_REGSAVE:
+      params.no_tls_get_addr_regsave = 0;
+      break;
+
+    case OPTION_NO_TLS_GET_ADDR_REGSAVE:
+      params.no_tls_get_addr_regsave = 1;
+      break;
+
     case OPTION_NO_OPD_OPT:
       no_opd_opt = 1;
       break;
index eb7bcb993383fa57392acd45dda66956c9995f1f..634b7a928081daa0af003fd6970b80c19718675e 100644 (file)
@@ -7595,18 +7595,27 @@ disable the optimization.
 @cindex PowerPC64 __tls_get_addr optimization
 @kindex --tls-get-addr-optimize
 @kindex --no-tls-get-addr-optimize
+@kindex --tls-get-addr-regsave
+@kindex --no-tls-get-addr-regsave
 @item --tls-get-addr-optimize
 @itemx --no-tls-get-addr-optimize
-These options control whether PowerPC64 @command{ld} uses a special
+These options control how PowerPC64 @command{ld} uses a special
 stub to call __tls_get_addr.  PowerPC64 glibc 2.22 and later support
 an optimization that allows the second and subsequent calls to
 @code{__tls_get_addr} for a given symbol to be resolved by the special
-stub without calling in to glibc.  By default the linker enables this
-option when glibc advertises the availability of __tls_get_addr_opt.
-Forcing this option on when using an older glibc won't do much besides
-slow down your applications, but may be useful if linking an
-application against an older glibc with the expectation that it will
-normally be used on systems having a newer glibc.
+stub without calling in to glibc.  By default the linker enables
+generation of the stub when glibc advertises the availability of
+__tls_get_addr_opt.
+Using @option{--tls-get-addr-optimize} with an older glibc won't do
+much besides slow down your applications, but may be useful if linking
+an application against an older glibc with the expectation that it
+will normally be used on systems having a newer glibc.
+@option{--tls-get-addr-regsave} forces generation of a stub that saves
+and restores volatile registers around the call into glibc.  Normally,
+this is done when the linker detects a call to __tls_get_addr_desc.
+Such calls then go via the register saving stub to __tls_get_addr_opt.
+@option {--no-tls-get-addr-regsave} disables generation of the
+register saves.
 
 @cindex PowerPC64 OPD optimization
 @kindex --no-opd-optimize
index b767b6cb00d30f979d9d9736328e024121bfb064..d50846c806a32ad8e461c1e737867256fa690b2d 100644 (file)
@@ -233,6 +233,24 @@ set ppc64elftests {
      {{readelf -WSsrl tlstocso.r} {objdump -dr tlstocso.d}
       {objdump -sj.got tlstocso.g} {objdump -sj.tdata tlstocso.t}}
      "tlstoc.so"}
+    {"TLS dynamic exec (--tls-get-addr-regsave)" "-melf64ppc --no-plt-align --no-ld-generated-unwind-info --hash-style=sysv --tls-get-addr-regsave tmpdir/tls.o tmpdir/libtlslib.so" "" "" {}
+     {{readelf -WSsrl tlsexers.r} {objdump -dr tlsexers.d}
+      {objdump -sj.got tlsexe.g} {objdump -sj.tdata tlsexe.t}}
+     "tlsexers"}
+    {"TLS dynamic exec (--no-tls-optimize --tls-get-addr-regsave)" "-melf64ppc --no-tls-optimize --tls-get-addr-regsave --no-plt-align --no-ld-generated-unwind-info --hash-style=sysv tmpdir/tls.o tmpdir/libtlslib.so" "" "" {}
+     {{readelf -WSsrl tlsexenors.r} {objdump -dr tlsexenors.d}
+      {objdump -sj.got tlsexeno.g} {objdump -sj.tdata tlsexe.t}}
+     "tlsexenors"}
+    {"TLSTOC dynamic exec (--tls-get-addr-regsave)" "-melf64ppc --tls-get-addr-regsave --no-plt-align --no-ld-generated-unwind-info --hash-style=sysv tmpdir/tlstoc.o tmpdir/libtlslib.so" ""
+     "" {}
+     {{readelf -WSsrl tlsexetocrs.r} {objdump -dr tlsexetocrs.d}
+      {objdump -sj.got tlsexetoc.g} {objdump -sj.tdata tlsexetoc.t}}
+     "tlsexetocrs"}
+    {"TLSTOC dynamic exec (--no-tls-optimize --tls-get-addr-regsave)" "-melf64ppc --no-tls-optimize --tls-get-addr-regsave --no-plt-align --no-ld-generated-unwind-info --hash-style=sysv tmpdir/tlstoc.o tmpdir/libtlslib.so" ""
+     "" {}
+     {{readelf -WSsrl tlsexetocrs.r} {objdump -dr tlsexetocnors.d}
+      {objdump -sj.got tlsexetocno.g} {objdump -sj.tdata tlsexetoc.t}}
+     "tlsexetocnors"}
     {"TLS markers" "-melf64ppc" "" "-a64"  {tlsmark.s tlslib.s}
      {{objdump -dr tlsmark.d}}
      "tlsmark"}
@@ -253,6 +271,15 @@ set ppc64elftests {
     {"TLS opt 5" "-melf64ppc -shared --hash-style=both --gc-sections --no-plt-localentry tmpdir/tlsdll.so" "" "-a64"  {tlsopt5.s}
      {{objdump -dr tlsopt5.d} {readelf -wf tlsopt5.wf}}
      "tlsopt5"}
+    {"TLS opt 6" "-melf64ppc -shared --hash-style=both --gc-sections --no-plt-localentry --tls-get-addr-regsave tmpdir/tlsdll.so" "" "-a64"  {tlsopt5.s}
+     {{objdump -dr tlsopt6.d} {readelf -wf tlsopt6.wf}}
+     "tlsopt6"}
+    {"TLSdesc" "-melf64ppc -shared --hash-style=both --no-plt-localentry tmpdir/libtlslib.so" "" "-a64"  {tlsdesc.s}
+     {{objdump -dr tlsdesc.d} {readelf -wf tlsdesc.wf}}
+     "tlsdesc"}
+    {"TLSdesc2" "-melf64ppc -shared --hash-style=both --no-plt-localentry tmpdir/tlsdll.so" "" "-a64"  {tlsdesc.s}
+     {{objdump -dr tlsdesc2.d} {readelf -wf tlsdesc2.wf}}
+     "tlsdesc2"}
     {"sym@tocbase" "-shared -melf64ppc" "" "-a64" {symtocbase-1.s symtocbase-2.s}
        {{objdump -dj.data symtocbase.d}} "symtocbase.so"}
     {"TOC opt" "-melf64ppc" "" "-a64"  {tocopt.s}
diff --git a/ld/testsuite/ld-powerpc/tlsdesc.d b/ld/testsuite/ld-powerpc/tlsdesc.d
new file mode 100644 (file)
index 0000000..7216357
--- /dev/null
@@ -0,0 +1,68 @@
+
+.*:     file format .*
+
+Disassembly of section \.text:
+
+.* <.*\.plt_call\.__tls_get_addr_opt>:
+.*:    (e8 03 00 00|00 00 03 e8)       ld      r0,0\(r3\)
+.*:    (e9 83 00 08|08 00 83 e9)       ld      r12,8\(r3\)
+.*:    (2c 20 00 00|00 00 20 2c)       cmpdi   r0,0
+.*:    (7c 60 1b 78|78 1b 60 7c)       mr      r0,r3
+.*:    (7c 6c 6a 14|14 6a 6c 7c)       add     r3,r12,r13
+.*:    (4d 82 00 20|20 00 82 4d)       beqlr
+.*:    (7c 03 03 78|78 03 03 7c)       mr      r3,r0
+.*:    (7c 08 02 a6|a6 02 08 7c)       mflr    r0
+.*:    (f8 01 00 10|10 00 01 f8)       std     r0,16\(r1\)
+.*:    (f8 81 ff b8|b8 ff 81 f8)       std     r4,-72\(r1\)
+.*:    (f8 a1 ff c0|c0 ff a1 f8)       std     r5,-64\(r1\)
+.*:    (f8 c1 ff c8|c8 ff c1 f8)       std     r6,-56\(r1\)
+.*:    (f8 e1 ff d0|d0 ff e1 f8)       std     r7,-48\(r1\)
+.*:    (f9 01 ff d8|d8 ff 01 f9)       std     r8,-40\(r1\)
+.*:    (f9 21 ff e0|e0 ff 21 f9)       std     r9,-32\(r1\)
+.*:    (f9 41 ff e8|e8 ff 41 f9)       std     r10,-24\(r1\)
+.*:    (f9 61 ff f0|f0 ff 61 f9)       std     r11,-16\(r1\)
+.*:    (f8 21 ff 81|81 ff 21 f8)       stdu    r1,-128\(r1\)
+.*:    (f8 41 00 28|28 00 41 f8)       std     r2,40\(r1\)
+.*:    (e9 82 80 30|30 80 82 e9)       ld      r12,-32720\(r2\)
+.*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*:    (7d 8b 62 78|78 62 8b 7d)       xor     r11,r12,r12
+.*:    (7c 42 5a 14|14 5a 42 7c)       add     r2,r2,r11
+.*:    (e8 42 80 38|38 80 42 e8)       ld      r2,-32712\(r2\)
+.*:    (4e 80 04 21|21 04 80 4e)       bctrl
+.*:    (e8 41 00 28|28 00 41 e8)       ld      r2,40\(r1\)
+.*:    (e8 81 00 38|38 00 81 e8)       ld      r4,56\(r1\)
+.*:    (e8 a1 00 40|40 00 a1 e8)       ld      r5,64\(r1\)
+.*:    (e8 c1 00 48|48 00 c1 e8)       ld      r6,72\(r1\)
+.*:    (e8 e1 00 50|50 00 e1 e8)       ld      r7,80\(r1\)
+.*:    (e9 01 00 58|58 00 01 e9)       ld      r8,88\(r1\)
+.*:    (e9 21 00 60|60 00 21 e9)       ld      r9,96\(r1\)
+.*:    (e9 41 00 68|68 00 41 e9)       ld      r10,104\(r1\)
+.*:    (e9 61 00 70|70 00 61 e9)       ld      r11,112\(r1\)
+.*:    (38 21 00 80|80 00 21 38)       addi    r1,r1,128
+.*:    (e8 01 00 10|10 00 01 e8)       ld      r0,16\(r1\)
+.*:    (7c 08 03 a6|a6 03 08 7c)       mtlr    r0
+.*:    (4e 80 00 20|20 00 80 4e)       blr
+       \.\.\.
+
+.* <_start>:
+.*:    (38 62 80 08|08 80 62 38)       addi    r3,r2,-32760
+.*:    (4b ff ff 5d|5d ff ff 4b)       bl      .* <.*\.plt_call\.__tls_get_addr_opt>
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (00 00 00 00|18 03 01 00)       .*
+.*:    (00 01 03 18|00 00 00 00)       .*
+
+.* <__glink_PLTresolve>:
+.*:    (7d 88 02 a6|a6 02 88 7d)       mflr    r12
+.*:    (42 9f 00 05|05 00 9f 42)       bcl     .*
+.*:    (7d 68 02 a6|a6 02 68 7d)       mflr    r11
+.*:    (e8 4b ff f0|f0 ff 4b e8)       ld      r2,-16\(r11\)
+.*:    (7d 88 03 a6|a6 03 88 7d)       mtlr    r12
+.*:    (7d 62 5a 14|14 5a 62 7d)       add     r11,r2,r11
+.*:    (e9 8b 00 00|00 00 8b e9)       ld      r12,0\(r11\)
+.*:    (e8 4b 00 08|08 00 4b e8)       ld      r2,8\(r11\)
+.*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*:    (e9 6b 00 10|10 00 6b e9)       ld      r11,16\(r11\)
+.*:    (4e 80 04 20|20 04 80 4e)       bctr
+.*:    (38 00 00 00|00 00 00 38)       li      r0,0
+.*:    (4b ff ff d0|d0 ff ff 4b)       b       .* <__glink_PLTresolve>
diff --git a/ld/testsuite/ld-powerpc/tlsdesc.s b/ld/testsuite/ld-powerpc/tlsdesc.s
new file mode 100644 (file)
index 0000000..0c94b72
--- /dev/null
@@ -0,0 +1,8 @@
+ .text
+ .globl _start
+_start:
+ .cfi_startproc
+ addi 3,2,gd@got@tlsgd
+ bl __tls_get_addr_desc(gd@tlsgd)
+ nop
+ .cfi_endproc
diff --git a/ld/testsuite/ld-powerpc/tlsdesc.wf b/ld/testsuite/ld-powerpc/tlsdesc.wf
new file mode 100644 (file)
index 0000000..09503fa
--- /dev/null
@@ -0,0 +1,50 @@
+Contents of the \.eh_frame section:
+
+
+0+ 0+10 0+ CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 4
+  Data alignment factor: -8
+  Return address column: 65
+  Augmentation data:     1b
+  DW_CFA_def_cfa: r1 ofs 0
+
+0+14 0+34 0+18 FDE cie=0+ pc=0+240\.\.0+2e0
+  DW_CFA_advance_loc: 72 to 0+288
+  DW_CFA_def_cfa_offset: 128
+  DW_CFA_offset_extended_sf: r65 at cfa\+16
+  DW_CFA_offset: r4 at cfa-72
+  DW_CFA_offset: r5 at cfa-64
+  DW_CFA_offset: r6 at cfa-56
+  DW_CFA_offset: r7 at cfa-48
+  DW_CFA_offset: r8 at cfa-40
+  DW_CFA_offset: r9 at cfa-32
+  DW_CFA_offset: r10 at cfa-24
+  DW_CFA_offset: r11 at cfa-16
+  DW_CFA_advance_loc: 68 to 0+2cc
+  DW_CFA_def_cfa_offset: 0
+  DW_CFA_restore: r4
+  DW_CFA_restore: r5
+  DW_CFA_restore: r6
+  DW_CFA_restore: r7
+  DW_CFA_restore: r8
+  DW_CFA_restore: r9
+  DW_CFA_restore: r10
+  DW_CFA_restore: r11
+  DW_CFA_advance_loc: 8 to 0+2d4
+  DW_CFA_restore_extended: r65
+  DW_CFA_nop
+  DW_CFA_nop
+
+0+4c 0+14 0+50 FDE cie=0+ pc=0+2f8\.\.0+32c
+  DW_CFA_advance_loc: 4 to 0+2fc
+  DW_CFA_register: r65 in r12
+  DW_CFA_advance_loc: 20 to 0+310
+  DW_CFA_restore_extended: r65
+
+0+64 0+10 0+68 FDE cie=0+ pc=0+2e0\.\.0+2ec
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
diff --git a/ld/testsuite/ld-powerpc/tlsdesc2.d b/ld/testsuite/ld-powerpc/tlsdesc2.d
new file mode 100644 (file)
index 0000000..47aedbe
--- /dev/null
@@ -0,0 +1,69 @@
+
+.*:     file format .*
+
+Disassembly of section \.text:
+
+.* <.*\.plt_call\.__tls_get_addr_opt@@GLIBC_2\.22>:
+.*:    (e8 03 00 00|00 00 03 e8)       ld      r0,0\(r3\)
+.*:    (e9 83 00 08|08 00 83 e9)       ld      r12,8\(r3\)
+.*:    (2c 20 00 00|00 00 20 2c)       cmpdi   r0,0
+.*:    (7c 60 1b 78|78 1b 60 7c)       mr      r0,r3
+.*:    (7c 6c 6a 14|14 6a 6c 7c)       add     r3,r12,r13
+.*:    (4d 82 00 20|20 00 82 4d)       beqlr
+.*:    (7c 03 03 78|78 03 03 7c)       mr      r3,r0
+.*:    (7c 08 02 a6|a6 02 08 7c)       mflr    r0
+.*:    (f8 01 00 10|10 00 01 f8)       std     r0,16\(r1\)
+.*:    (f8 81 ff c0|c0 ff 81 f8)       std     r4,-64\(r1\)
+.*:    (f8 a1 ff c8|c8 ff a1 f8)       std     r5,-56\(r1\)
+.*:    (f8 c1 ff d0|d0 ff c1 f8)       std     r6,-48\(r1\)
+.*:    (f8 e1 ff d8|d8 ff e1 f8)       std     r7,-40\(r1\)
+.*:    (f9 01 ff e0|e0 ff 01 f9)       std     r8,-32\(r1\)
+.*:    (f9 21 ff e8|e8 ff 21 f9)       std     r9,-24\(r1\)
+.*:    (f9 41 ff f0|f0 ff 41 f9)       std     r10,-16\(r1\)
+.*:    (f9 61 ff f8|f8 ff 61 f9)       std     r11,-8\(r1\)
+.*:    (f8 21 ff a1|a1 ff 21 f8)       stdu    r1,-96\(r1\)
+.*:    (f8 41 00 18|18 00 41 f8)       std     r2,24\(r1\)
+.*:    (e9 82 80 28|28 80 82 e9)       ld      r12,-32728\(r2\)
+.*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*:    (4e 80 04 21|21 04 80 4e)       bctrl
+.*:    (e8 41 00 18|18 00 41 e8)       ld      r2,24\(r1\)
+.*:    (e8 81 00 20|20 00 81 e8)       ld      r4,32\(r1\)
+.*:    (e8 a1 00 28|28 00 a1 e8)       ld      r5,40\(r1\)
+.*:    (e8 c1 00 30|30 00 c1 e8)       ld      r6,48\(r1\)
+.*:    (e8 e1 00 38|38 00 e1 e8)       ld      r7,56\(r1\)
+.*:    (e9 01 00 40|40 00 01 e9)       ld      r8,64\(r1\)
+.*:    (e9 21 00 48|48 00 21 e9)       ld      r9,72\(r1\)
+.*:    (e9 41 00 50|50 00 41 e9)       ld      r10,80\(r1\)
+.*:    (e9 61 00 58|58 00 61 e9)       ld      r11,88\(r1\)
+.*:    (38 21 00 60|60 00 21 38)       addi    r1,r1,96
+.*:    (e8 01 00 10|10 00 01 e8)       ld      r0,16\(r1\)
+.*:    (7c 08 03 a6|a6 03 08 7c)       mtlr    r0
+.*:    (4e 80 00 20|20 00 80 4e)       blr
+       \.\.\.
+
+.* <_start>:
+.*:    (38 62 80 08|08 80 62 38)       addi    r3,r2,-32760
+.*:    (4b ff ff 5d|5d ff ff 4b)       bl      .* <.*\.plt_call\.__tls_get_addr_opt@@GLIBC_2\.22>
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (00 00 00 00|f8 02 01 00)       .*
+.*:    (00 01 02 f8|00 00 00 00)       .*
+
+.* <__glink_PLTresolve>:
+.*:    (7c 08 02 a6|a6 02 08 7c)       mflr    r0
+.*:    (42 9f 00 05|05 00 9f 42)       bcl     .*
+.*:    (7d 68 02 a6|a6 02 68 7d)       mflr    r11
+.*:    (f8 41 00 18|18 00 41 f8)       std     r2,24\(r1\)
+.*:    (e8 4b ff f0|f0 ff 4b e8)       ld      r2,-16\(r11\)
+.*:    (7c 08 03 a6|a6 03 08 7c)       mtlr    r0
+.*:    (7d 8b 60 50|50 60 8b 7d)       subf    r12,r11,r12
+.*:    (7d 62 5a 14|14 5a 62 7d)       add     r11,r2,r11
+.*:    (38 0c ff d0|d0 ff 0c 38)       addi    r0,r12,-48
+.*:    (e9 8b 00 00|00 00 8b e9)       ld      r12,0\(r11\)
+.*:    (78 00 f0 82|82 f0 00 78)       rldicl  r0,r0,62,2
+.*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*:    (e9 6b 00 08|08 00 6b e9)       ld      r11,8\(r11\)
+.*:    (4e 80 04 20|20 04 80 4e)       bctr
+
+.* <__tls_get_addr_opt@plt>:
+.*:    (4b ff ff c8|c8 ff ff 4b)       b       .* <__glink_PLTresolve>
diff --git a/ld/testsuite/ld-powerpc/tlsdesc2.wf b/ld/testsuite/ld-powerpc/tlsdesc2.wf
new file mode 100644 (file)
index 0000000..cb92c29
--- /dev/null
@@ -0,0 +1,49 @@
+Contents of the \.eh_frame section:
+
+0+ 0+10 0+ CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 4
+  Data alignment factor: -8
+  Return address column: 65
+  Augmentation data:     1b
+  DW_CFA_def_cfa: r1 ofs 0
+
+0+14 0+34 0+18 FDE cie=0+ pc=0+260\.\.0+300
+  DW_CFA_advance_loc: 72 to 0+2a8
+  DW_CFA_def_cfa_offset: 96
+  DW_CFA_offset_extended_sf: r65 at cfa\+16
+  DW_CFA_offset: r4 at cfa-64
+  DW_CFA_offset: r5 at cfa-56
+  DW_CFA_offset: r6 at cfa-48
+  DW_CFA_offset: r7 at cfa-40
+  DW_CFA_offset: r8 at cfa-32
+  DW_CFA_offset: r9 at cfa-24
+  DW_CFA_offset: r10 at cfa-16
+  DW_CFA_offset: r11 at cfa-8
+  DW_CFA_advance_loc: 56 to 0+2e0
+  DW_CFA_def_cfa_offset: 0
+  DW_CFA_restore: r4
+  DW_CFA_restore: r5
+  DW_CFA_restore: r6
+  DW_CFA_restore: r7
+  DW_CFA_restore: r8
+  DW_CFA_restore: r9
+  DW_CFA_restore: r10
+  DW_CFA_restore: r11
+  DW_CFA_advance_loc: 8 to 0+2e8
+  DW_CFA_restore_extended: r65
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+0+4c 0+14 0+50 FDE cie=0+ pc=0+318\.\.0+354
+  DW_CFA_advance_loc: 4 to 0+31c
+  DW_CFA_register: r65 in r0
+  DW_CFA_advance_loc: 28 to 0+338
+  DW_CFA_restore_extended: r65
+
+0+64 0+10 0+68 FDE cie=0+ pc=0+300\.\.0+30c
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
diff --git a/ld/testsuite/ld-powerpc/tlsexenors.d b/ld/testsuite/ld-powerpc/tlsexenors.d
new file mode 100644 (file)
index 0000000..09c9705
--- /dev/null
@@ -0,0 +1,106 @@
+#source: tls.s
+#as: -a64
+#ld: --no-tls-optimize tmpdir/libtlslib.so
+#objdump: -dr
+#target: powerpc64*-*-*
+
+.*
+
+Disassembly of section \.text:
+
+.* <.*plt_call\.__tls_get_addr(|_opt)>:
+.*:    (e8 03 00 00|00 00 03 e8)       ld      r0,0\(r3\)
+.*:    (e9 83 00 08|08 00 83 e9)       ld      r12,8\(r3\)
+.*:    (2c 20 00 00|00 00 20 2c)       cmpdi   r0,0
+.*:    (7c 60 1b 78|78 1b 60 7c)       mr      r0,r3
+.*:    (7c 6c 6a 14|14 6a 6c 7c)       add     r3,r12,r13
+.*:    (4d 82 00 20|20 00 82 4d)       beqlr *
+.*:    (7c 03 03 78|78 03 03 7c)       mr      r3,r0
+.*:    (7c 08 02 a6|a6 02 08 7c)       mflr    r0
+.*:    (f8 01 00 10|10 00 01 f8)       std     r0,16\(r1\)
+.*:    (f8 81 ff b8|b8 ff 81 f8)       std     r4,-72\(r1\)
+.*:    (f8 a1 ff c0|c0 ff a1 f8)       std     r5,-64\(r1\)
+.*:    (f8 c1 ff c8|c8 ff c1 f8)       std     r6,-56\(r1\)
+.*:    (f8 e1 ff d0|d0 ff e1 f8)       std     r7,-48\(r1\)
+.*:    (f9 01 ff d8|d8 ff 01 f9)       std     r8,-40\(r1\)
+.*:    (f9 21 ff e0|e0 ff 21 f9)       std     r9,-32\(r1\)
+.*:    (f9 41 ff e8|e8 ff 41 f9)       std     r10,-24\(r1\)
+.*:    (f9 61 ff f0|f0 ff 61 f9)       std     r11,-16\(r1\)
+.*:    (f8 21 ff 81|81 ff 21 f8)       stdu    r1,-128\(r1\)
+.*:    (f8 41 00 28|28 00 41 f8)       std     r2,40\(r1\)
+.*:    (e9 82 80 88|88 80 82 e9)       ld      r12,-32632\(r2\)
+.*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*:    (e8 42 80 90|90 80 42 e8)       ld      r2,-32624\(r2\)
+.*:    (4e 80 04 21|21 04 80 4e)       bctrl
+.*:    (e8 41 00 28|28 00 41 e8)       ld      r2,40\(r1\)
+.*:    (e8 81 00 38|38 00 81 e8)       ld      r4,56\(r1\)
+.*:    (e8 a1 00 40|40 00 a1 e8)       ld      r5,64\(r1\)
+.*:    (e8 c1 00 48|48 00 c1 e8)       ld      r6,72\(r1\)
+.*:    (e8 e1 00 50|50 00 e1 e8)       ld      r7,80\(r1\)
+.*:    (e9 01 00 58|58 00 01 e9)       ld      r8,88\(r1\)
+.*:    (e9 21 00 60|60 00 21 e9)       ld      r9,96\(r1\)
+.*:    (e9 41 00 68|68 00 41 e9)       ld      r10,104\(r1\)
+.*:    (e9 61 00 70|70 00 61 e9)       ld      r11,112\(r1\)
+.*:    (38 21 00 80|80 00 21 38)       addi    r1,r1,128
+.*:    (e8 01 00 10|10 00 01 e8)       ld      r0,16\(r1\)
+.*:    (7c 08 03 a6|a6 03 08 7c)       mtlr    r0
+.*:    (4e 80 00 20|20 00 80 4e)       blr
+
+.* <\._start>:
+.*:    (38 62 80 20|20 80 62 38)       addi    r3,r2,-32736
+.*:    (4b ff ff 6d|6d ff ff 4b)       bl      .*
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (38 62 80 30|30 80 62 38)       addi    r3,r2,-32720
+.*:    (4b ff ff 61|61 ff ff 4b)       bl      .*
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (38 62 80 48|48 80 62 38)       addi    r3,r2,-32696
+.*:    (4b ff ff 55|55 ff ff 4b)       bl      .*
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (38 62 80 60|60 80 62 38)       addi    r3,r2,-32672
+.*:    (4b ff ff 49|49 ff ff 4b)       bl      .*
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (39 23 80 40|40 80 23 39)       addi    r9,r3,-32704
+.*:    (3d 23 00 00|00 00 23 3d)       addis   r9,r3,0
+.*:    (81 49 80 48|48 80 49 81)       lwz     r10,-32696\(r9\)
+.*:    (e9 22 80 40|40 80 22 e9)       ld      r9,-32704\(r2\)
+.*:    (7d 49 18 2a|2a 18 49 7d)       ldx     r10,r9,r3
+.*:    (e9 22 80 58|58 80 22 e9)       ld      r9,-32680\(r2\)
+.*:    (7d 49 6a 2e|2e 6a 49 7d)       lhzx    r10,r9,r13
+.*:    (89 4d 90 60|60 90 4d 89)       lbz     r10,-28576\(r13\)
+.*:    (3d 2d 00 00|00 00 2d 3d)       addis   r9,r13,0
+.*:    (99 49 90 68|68 90 49 99)       stb     r10,-28568\(r9\)
+.*:    (38 62 80 08|08 80 62 38)       addi    r3,r2,-32760
+.*:    (4b ff ff 15|15 ff ff 4b)       bl      .*
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (38 62 80 60|60 80 62 38)       addi    r3,r2,-32672
+.*:    (4b ff ff 09|09 ff ff 4b)       bl      .*
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (f9 43 80 08|08 80 43 f9)       std     r10,-32760\(r3\)
+.*:    (3d 23 00 00|00 00 23 3d)       addis   r9,r3,0
+.*:    (91 49 80 10|10 80 49 91)       stw     r10,-32752\(r9\)
+.*:    (e9 22 80 18|18 80 22 e9)       ld      r9,-32744\(r2\)
+.*:    (7d 49 19 2a|2a 19 49 7d)       stdx    r10,r9,r3
+.*:    (e9 22 80 58|58 80 22 e9)       ld      r9,-32680\(r2\)
+.*:    (7d 49 6b 2e|2e 6b 49 7d)       sthx    r10,r9,r13
+.*:    (e9 4d 90 2a|2a 90 4d e9)       lwa     r10,-28632\(r13\)
+.*:    (3d 2d 00 00|00 00 2d 3d)       addis   r9,r13,0
+.*:    (a9 49 90 30|30 90 49 a9)       lha     r10,-28624\(r9\)
+.*:    (00 00 00 00|78 02 01 00)       .*
+.*:    (00 01 02 78|00 00 00 00)       .*
+
+.* <__glink_PLTresolve>:
+.*:    (7d 88 02 a6|a6 02 88 7d)       mflr    r12
+.*:    (42 9f 00 05|05 00 9f 42)       bcl     .*
+.*:    (7d 68 02 a6|a6 02 68 7d)       mflr    r11
+.*:    (e8 4b ff f0|f0 ff 4b e8)       ld      r2,-16\(r11\)
+.*:    (7d 88 03 a6|a6 03 88 7d)       mtlr    r12
+.*:    (7d 62 5a 14|14 5a 62 7d)       add     r11,r2,r11
+.*:    (e9 8b 00 00|00 00 8b e9)       ld      r12,0\(r11\)
+.*:    (e8 4b 00 08|08 00 4b e8)       ld      r2,8\(r11\)
+.*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*:    (e9 6b 00 10|10 00 6b e9)       ld      r11,16\(r11\)
+.*:    (4e 80 04 20|20 04 80 4e)       bctr
+
+.* <__tls_get_addr_opt@plt>:
+.*:    (38 00 00 00|00 00 00 38)       li      r0,0
+.*:    (4b ff ff d0|d0 ff ff 4b)       b       .* <__glink_PLTresolve>
diff --git a/ld/testsuite/ld-powerpc/tlsexenors.r b/ld/testsuite/ld-powerpc/tlsexenors.r
new file mode 100644 (file)
index 0000000..e25fecd
--- /dev/null
@@ -0,0 +1,113 @@
+#source: tls.s
+#source: tlslib.s
+#as: -a64
+#ld: --no-tls-optimize
+#readelf: -WSsrl
+#target: powerpc64*-*-*
+
+There are [0-9]+ section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+ +\[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+ +\[[ 0-9]+\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+ +\[[ 0-9]+\] \.interp +.*
+ +\[[ 0-9]+\] \.hash +.*
+ +\[[ 0-9]+\] \.dynsym +.*
+ +\[[ 0-9]+\] \.dynstr +.*
+ +\[[ 0-9]+\] \.rela\.dyn +.*
+ +\[[ 0-9]+\] \.rela\.plt +.*
+ +\[[ 0-9]+\] \.text +PROGBITS .* 0+164 0+ +AX +0 +0 +32
+ +\[[ 0-9]+\] \.tdata +PROGBITS .* 0+38 0+ WAT +0 +0 +8
+ +\[[ 0-9]+\] \.tbss +NOBITS .* 0+38 0+ WAT +0 +0 +8
+ +\[[ 0-9]+\] \.dynamic +DYNAMIC .* 0+160 10 +WA +4 +0 +8
+ +\[[ 0-9]+\] \.opd .*
+ +\[[ 0-9]+\] \.got +PROGBITS .* 0+70 08 +WA +0 +0 +256
+ +\[[ 0-9]+\] \.plt +.*
+ +\[[ 0-9]+\] \.symtab +.*
+ +\[[ 0-9]+\] \.strtab +.*
+ +\[[ 0-9]+\] \.shstrtab +.*
+#...
+
+Elf file type is EXEC \(Executable file\)
+Entry point .*
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+ +Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+ +PHDR +0x0+40 0x0+10000040 0x0+10000040 0x0+150 0x0+150 R +0x8
+ +INTERP +0x0+190 0x0+10000190 0x0+10000190 0x0+11 0x0+11 R +0x1
+ +\[Requesting program interpreter: .*\]
+ +LOAD .* R E 0x10000
+ +LOAD .* RW +0x10000
+ +DYNAMIC .* RW +0x8
+ +TLS .* 0x0+38 0x0+70 R +0x8
+
+ Section to Segment mapping:
+ +Segment Sections\.\.\.
+ +0+ +
+ +01 +\.interp *
+ +02 +\.interp \.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text *
+ +03 +\.tdata \.dynamic \.opd \.got \.plt *
+ +04 +\.dynamic *
+ +05 +\.tdata \.tbss *
+
+Relocation section '\.rela\.dyn' at offset .* contains 3 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-f ]+R_PPC64_DTPMOD64 +0+ gd \+ 0
+[0-9a-f ]+R_PPC64_DTPREL64 +0+ gd \+ 0
+[0-9a-f ]+R_PPC64_DTPMOD64 +0+ ld \+ 0
+
+Relocation section '\.rela\.plt' at offset .* contains 1 entry:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-f ]+R_PPC64_JMP_SLOT +0+ __tls_get_addr_opt \+ 0
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+.* NOTYPE +LOCAL +DEFAULT +UND *
+.* TLS +GLOBAL +DEFAULT +UND gd
+.* TLS +GLOBAL +DEFAULT +UND ld
+.* FUNC +GLOBAL +DEFAULT +UND __tls_get_addr_opt
+
+Symbol table '\.symtab' contains [0-9]+ entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+.* 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND *
+.* SECTION +LOCAL +DEFAULT +1 *
+.* SECTION +LOCAL +DEFAULT +2 *
+.* SECTION +LOCAL +DEFAULT +3 *
+.* SECTION +LOCAL +DEFAULT +4 *
+.* SECTION +LOCAL +DEFAULT +5 *
+.* SECTION +LOCAL +DEFAULT +6 *
+.* SECTION +LOCAL +DEFAULT +7 *
+.* SECTION +LOCAL +DEFAULT +8 *
+.* SECTION +LOCAL +DEFAULT +9 *
+.* SECTION +LOCAL +DEFAULT +10 *
+.* SECTION +LOCAL +DEFAULT +11 *
+.* SECTION +LOCAL +DEFAULT +12 *
+.* SECTION +LOCAL +DEFAULT +13 *
+.* FILE +LOCAL +DEFAULT +ABS .*
+.* NOTYPE +LOCAL +DEFAULT +ABS TLSMARK
+.* TLS +LOCAL +DEFAULT +8 gd4
+.* TLS +LOCAL +DEFAULT +8 ld4
+.* TLS +LOCAL +DEFAULT +8 ld5
+.* TLS +LOCAL +DEFAULT +8 ld6
+.* TLS +LOCAL +DEFAULT +8 ie4
+.* TLS +LOCAL +DEFAULT +8 le4
+.* TLS +LOCAL +DEFAULT +8 le5
+.* FILE +LOCAL +DEFAULT +ABS 
+.* OBJECT +LOCAL +DEFAULT +10 _DYNAMIC
+.* NOTYPE +LOCAL +DEFAULT +7 __glink_PLTresolve
+.* NOTYPE +LOCAL +DEFAULT +7 .*\.plt_call\.__tls_get_addr(|_opt)
+.* GLOBAL +DEFAULT +UND gd
+.* GLOBAL +DEFAULT +9 le0
+.* GLOBAL +DEFAULT +9 ld0
+.* GLOBAL +DEFAULT +9 le1
+.* GLOBAL +DEFAULT +UND ld
+.* FUNC +GLOBAL +DEFAULT +11 _start
+.* TLS +GLOBAL +DEFAULT +9 ld2
+.* TLS +GLOBAL +DEFAULT +9 ld1
+.* NOTYPE +GLOBAL +DEFAULT +13 __bss_start
+.* FUNC +GLOBAL +DEFAULT +UND __tls_get_addr_opt
+.* NOTYPE +GLOBAL +DEFAULT +13 _edata
+.* NOTYPE +GLOBAL +DEFAULT +13 _end
+.* TLS +GLOBAL +DEFAULT +9 gd0
+.* TLS +GLOBAL +DEFAULT +9 ie0
diff --git a/ld/testsuite/ld-powerpc/tlsexers.d b/ld/testsuite/ld-powerpc/tlsexers.d
new file mode 100644 (file)
index 0000000..5400d8e
--- /dev/null
@@ -0,0 +1,104 @@
+#source: tls.s
+#as: -a64
+#ld: tmpdir/libtlslib.so
+#objdump: -dr
+#target: powerpc64*-*-*
+
+.*
+
+Disassembly of section \.text:
+
+.* <.*plt_call\.__tls_get_addr(|_opt)>:
+.*     (e8 03 00 00|00 00 03 e8)       ld      r0,0\(r3\)
+.*     (e9 83 00 08|08 00 83 e9)       ld      r12,8\(r3\)
+.*     (2c 20 00 00|00 00 20 2c)       cmpdi   r0,0
+.*     (7c 60 1b 78|78 1b 60 7c)       mr      r0,r3
+.*     (7c 6c 6a 14|14 6a 6c 7c)       add     r3,r12,r13
+.*     (4d 82 00 20|20 00 82 4d)       beqlr *
+.*     (7c 03 03 78|78 03 03 7c)       mr      r3,r0
+.*     (7c 08 02 a6|a6 02 08 7c)       mflr    r0
+.*     (f8 01 00 10|10 00 01 f8)       std     r0,16\(r1\)
+.*     (f8 81 ff b8|b8 ff 81 f8)       std     r4,-72\(r1\)
+.*     (f8 a1 ff c0|c0 ff a1 f8)       std     r5,-64\(r1\)
+.*     (f8 c1 ff c8|c8 ff c1 f8)       std     r6,-56\(r1\)
+.*     (f8 e1 ff d0|d0 ff e1 f8)       std     r7,-48\(r1\)
+.*     (f9 01 ff d8|d8 ff 01 f9)       std     r8,-40\(r1\)
+.*     (f9 21 ff e0|e0 ff 21 f9)       std     r9,-32\(r1\)
+.*     (f9 41 ff e8|e8 ff 41 f9)       std     r10,-24\(r1\)
+.*     (f9 61 ff f0|f0 ff 61 f9)       std     r11,-16\(r1\)
+.*     (f8 21 ff 81|81 ff 21 f8)       stdu    r1,-128\(r1\)
+.*     (f8 41 00 28|28 00 41 f8)       std     r2,40\(r1\)
+.*     (e9 82 80 48|48 80 82 e9)       ld      r12,-32696\(r2\)
+.*     (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*     (e8 42 80 50|50 80 42 e8)       ld      r2,-32688\(r2\)
+.*     (4e 80 04 21|21 04 80 4e)       bctrl
+.*     (e8 41 00 28|28 00 41 e8)       ld      r2,40\(r1\)
+.*     (e8 81 00 38|38 00 81 e8)       ld      r4,56\(r1\)
+.*     (e8 a1 00 40|40 00 a1 e8)       ld      r5,64\(r1\)
+.*     (e8 c1 00 48|48 00 c1 e8)       ld      r6,72\(r1\)
+.*     (e8 e1 00 50|50 00 e1 e8)       ld      r7,80\(r1\)
+.*     (e9 01 00 58|58 00 01 e9)       ld      r8,88\(r1\)
+.*     (e9 21 00 60|60 00 21 e9)       ld      r9,96\(r1\)
+.*     (e9 41 00 68|68 00 41 e9)       ld      r10,104\(r1\)
+.*     (e9 61 00 70|70 00 61 e9)       ld      r11,112\(r1\)
+.*     (38 21 00 80|80 00 21 38)       addi    r1,r1,128
+.*     (e8 01 00 10|10 00 01 e8)       ld      r0,16\(r1\)
+.*     (7c 08 03 a6|a6 03 08 7c)       mtlr    r0
+.*     (4e 80 00 20|20 00 80 4e)       blr
+
+.* <._start>:
+.*     (e8 62 80 10|10 80 62 e8)       ld      r3,-32752\(r2\)
+.*     (7c 63 6a 14|14 6a 63 7c)       add     r3,r3,r13
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (38 62 80 18|18 80 62 38)       addi    r3,r2,-32744
+.*     (4b ff ff 61|61 ff ff 4b)       bl      .*
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (38 6d 90 38|38 90 6d 38)       addi    r3,r13,-28616
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (38 6d 10 00|00 10 6d 38)       addi    r3,r13,4096
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (39 23 80 40|40 80 23 39)       addi    r9,r3,-32704
+.*     (3d 23 00 00|00 00 23 3d)       addis   r9,r3,0
+.*     (81 49 80 48|48 80 49 81)       lwz     r10,-32696\(r9\)
+.*     (e9 22 80 28|28 80 22 e9)       ld      r9,-32728\(r2\)
+.*     (7d 49 18 2a|2a 18 49 7d)       ldx     r10,r9,r3
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (a1 4d 90 58|58 90 4d a1)       lhz     r10,-28584\(r13\)
+.*     (89 4d 90 60|60 90 4d 89)       lbz     r10,-28576\(r13\)
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (99 4d 90 68|68 90 4d 99)       stb     r10,-28568\(r13\)
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (38 6d 90 00|00 90 6d 38)       addi    r3,r13,-28672
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (38 6d 10 00|00 10 6d 38)       addi    r3,r13,4096
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (f9 43 80 08|08 80 43 f9)       std     r10,-32760\(r3\)
+.*     (3d 23 00 00|00 00 23 3d)       addis   r9,r3,0
+.*     (91 49 80 10|10 80 49 91)       stw     r10,-32752\(r9\)
+.*     (e9 22 80 08|08 80 22 e9)       ld      r9,-32760\(r2\)
+.*     (7d 49 19 2a|2a 19 49 7d)       stdx    r10,r9,r3
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (b1 4d 90 58|58 90 4d b1)       sth     r10,-28584\(r13\)
+.*     (e9 4d 90 2a|2a 90 4d e9)       lwa     r10,-28632\(r13\)
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (a9 4d 90 30|30 90 4d a9)       lha     r10,-28624\(r13\)
+.*     (00 00 00 00|38 02 01 00) .*
+.*     (00 01 02 38|00 00 00 00) .*
+.* <__glink_PLTresolve>:
+.*     (7d 88 02 a6|a6 02 88 7d)       mflr    r12
+.*     (42 9f 00 05|05 00 9f 42)       bcl     20,4\*cr7\+so,.*
+.*     (7d 68 02 a6|a6 02 68 7d)       mflr    r11
+.*     (e8 4b ff f0|f0 ff 4b e8)       ld      r2,-16\(r11\)
+.*     (7d 88 03 a6|a6 03 88 7d)       mtlr    r12
+.*     (7d 62 5a 14|14 5a 62 7d)       add     r11,r2,r11
+.*     (e9 8b 00 00|00 00 8b e9)       ld      r12,0\(r11\)
+.*     (e8 4b 00 08|08 00 4b e8)       ld      r2,8\(r11\)
+.*     (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*     (e9 6b 00 10|10 00 6b e9)       ld      r11,16\(r11\)
+.*     (4e 80 04 20|20 04 80 4e)       bctr
+.* <__tls_get_addr_opt@plt>:
+.*     (38 00 00 00|00 00 00 38)       li      r0,0
+.*     (4b ff ff d0|d0 ff ff 4b)       b       .*
diff --git a/ld/testsuite/ld-powerpc/tlsexers.r b/ld/testsuite/ld-powerpc/tlsexers.r
new file mode 100644 (file)
index 0000000..3940dad
--- /dev/null
@@ -0,0 +1,112 @@
+#source: tls.s
+#source: tlslib.s
+#as: -a64
+#ld:
+#readelf: -WSsrl
+#target: powerpc64*-*-*
+
+There are [0-9]+ section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+ +\[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+ +\[[ 0-9]+\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+ +\[[ 0-9]+\] \.interp +.*
+ +\[[ 0-9]+\] \.hash +.*
+ +\[[ 0-9]+\] \.dynsym +.*
+ +\[[ 0-9]+\] \.dynstr +.*
+ +\[[ 0-9]+\] \.rela\.dyn +.*
+ +\[[ 0-9]+\] \.rela\.plt +.*
+ +\[[ 0-9]+\] \.text +PROGBITS .* 0+164 0+ +AX +0 +0 +32
+ +\[[ 0-9]+\] \.tdata +PROGBITS .* 0+38 0+ WAT +0 +0 +8
+ +\[[ 0-9]+\] \.tbss +NOBITS .* 0+38 0+ WAT +0 +0 +8
+ +\[[ 0-9]+\] \.dynamic +DYNAMIC .* 0+160 10 +WA +4 +0 +8
+ +\[[ 0-9]+\] \.opd .*
+ +\[[ 0-9]+\] \.got +PROGBITS .* 0+30 08 +WA +0 +0 +256
+ +\[[ 0-9]+\] \.plt +.*
+ +\[[ 0-9]+\] \.symtab +.*
+ +\[[ 0-9]+\] \.strtab +.*
+ +\[[ 0-9]+\] \.shstrtab +.*
+#...
+
+Elf file type is EXEC \(Executable file\)
+Entry point .*
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+ +Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+ +PHDR +0x0+40 0x0+10000040 0x0+10000040 0x0+150 0x0+150 R +0x8
+ +INTERP +0x0+190 0x0+10000190 0x0+10000190 0x0+11 0x0+11 R +0x1
+ +\[Requesting program interpreter: .*\]
+ +LOAD .* R E 0x10000
+ +LOAD .* RW +0x10000
+ +DYNAMIC .* RW +0x8
+ +TLS .* 0x0+38 0x0+70 R +0x8
+
+ Section to Segment mapping:
+ +Segment Sections\.\.\.
+ +0+ +
+ +01 +\.interp *
+ +02 +\.interp \.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text *
+ +03 +\.tdata \.dynamic \.opd \.got \.plt *
+ +04 +\.dynamic *
+ +05 +\.tdata \.tbss *
+
+Relocation section '\.rela\.dyn' at offset .* contains 2 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-f ]+R_PPC64_TPREL64 +0+ gd \+ 0
+[0-9a-f ]+R_PPC64_DTPMOD64 +0+ ld \+ 0
+
+Relocation section '\.rela\.plt' at offset .* contains 1 entry:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-f ]+R_PPC64_JMP_SLOT +0+ __tls_get_addr_opt \+ 0
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+.* NOTYPE +LOCAL +DEFAULT +UND *
+.* TLS +GLOBAL +DEFAULT +UND gd
+.* TLS +GLOBAL +DEFAULT +UND ld
+.* FUNC +GLOBAL +DEFAULT +UND __tls_get_addr_opt
+
+Symbol table '\.symtab' contains [0-9]+ entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+.* 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND *
+.* SECTION +LOCAL +DEFAULT +1 *
+.* SECTION +LOCAL +DEFAULT +2 *
+.* SECTION +LOCAL +DEFAULT +3 *
+.* SECTION +LOCAL +DEFAULT +4 *
+.* SECTION +LOCAL +DEFAULT +5 *
+.* SECTION +LOCAL +DEFAULT +6 *
+.* SECTION +LOCAL +DEFAULT +7 *
+.* SECTION +LOCAL +DEFAULT +8 *
+.* SECTION +LOCAL +DEFAULT +9 *
+.* SECTION +LOCAL +DEFAULT +10 *
+.* SECTION +LOCAL +DEFAULT +11 *
+.* SECTION +LOCAL +DEFAULT +12 *
+.* SECTION +LOCAL +DEFAULT +13 *
+.* FILE +LOCAL +DEFAULT +ABS .*
+.* NOTYPE +LOCAL +DEFAULT +ABS TLSMARK
+.* TLS +LOCAL +DEFAULT +8 gd4
+.* TLS +LOCAL +DEFAULT +8 ld4
+.* TLS +LOCAL +DEFAULT +8 ld5
+.* TLS +LOCAL +DEFAULT +8 ld6
+.* TLS +LOCAL +DEFAULT +8 ie4
+.* TLS +LOCAL +DEFAULT +8 le4
+.* TLS +LOCAL +DEFAULT +8 le5
+.* FILE +LOCAL +DEFAULT +ABS 
+.* OBJECT +LOCAL +DEFAULT +10 _DYNAMIC
+.* NOTYPE +LOCAL +DEFAULT +7 __glink_PLTresolve
+.* NOTYPE +LOCAL +DEFAULT +7 .*\.plt_call\.__tls_get_addr(|_opt)
+.* GLOBAL +DEFAULT +UND gd
+.* GLOBAL +DEFAULT +9 le0
+.* GLOBAL +DEFAULT +9 ld0
+.* GLOBAL +DEFAULT +9 le1
+.* GLOBAL +DEFAULT +UND ld
+.* FUNC +GLOBAL +DEFAULT +11 _start
+.* TLS +GLOBAL +DEFAULT +9 ld2
+.* TLS +GLOBAL +DEFAULT +9 ld1
+.* NOTYPE +GLOBAL +DEFAULT +13 __bss_start
+.* FUNC +GLOBAL +DEFAULT +UND __tls_get_addr_opt
+.* NOTYPE +GLOBAL +DEFAULT +13 _edata
+.* NOTYPE +GLOBAL +DEFAULT +13 _end
+.* TLS +GLOBAL +DEFAULT +9 gd0
+.* TLS +GLOBAL +DEFAULT +9 ie0
diff --git a/ld/testsuite/ld-powerpc/tlsexetocnors.d b/ld/testsuite/ld-powerpc/tlsexetocnors.d
new file mode 100644 (file)
index 0000000..53e9630
--- /dev/null
@@ -0,0 +1,90 @@
+#source: tlstoc.s
+#as: -a64
+#ld: --no-tls-optimize tmpdir/libtlslib.so
+#objdump: -dr
+#target: powerpc64*-*-*
+
+.*
+
+Disassembly of section \.text:
+
+.* <.*plt_call\.__tls_get_addr(|_opt)>:
+.*:    (e8 03 00 00|00 00 03 e8)       ld      r0,0\(r3\)
+.*:    (e9 83 00 08|08 00 83 e9)       ld      r12,8\(r3\)
+.*:    (2c 20 00 00|00 00 20 2c)       cmpdi   r0,0
+.*:    (7c 60 1b 78|78 1b 60 7c)       mr      r0,r3
+.*:    (7c 6c 6a 14|14 6a 6c 7c)       add     r3,r12,r13
+.*:    (4d 82 00 20|20 00 82 4d)       beqlr *
+.*:    (7c 03 03 78|78 03 03 7c)       mr      r3,r0
+.*:    (7c 08 02 a6|a6 02 08 7c)       mflr    r0
+.*:    (f8 01 00 10|10 00 01 f8)       std     r0,16\(r1\)
+.*:    (f8 81 ff b8|b8 ff 81 f8)       std     r4,-72\(r1\)
+.*:    (f8 a1 ff c0|c0 ff a1 f8)       std     r5,-64\(r1\)
+.*:    (f8 c1 ff c8|c8 ff c1 f8)       std     r6,-56\(r1\)
+.*:    (f8 e1 ff d0|d0 ff e1 f8)       std     r7,-48\(r1\)
+.*:    (f9 01 ff d8|d8 ff 01 f9)       std     r8,-40\(r1\)
+.*:    (f9 21 ff e0|e0 ff 21 f9)       std     r9,-32\(r1\)
+.*:    (f9 41 ff e8|e8 ff 41 f9)       std     r10,-24\(r1\)
+.*:    (f9 61 ff f0|f0 ff 61 f9)       std     r11,-16\(r1\)
+.*:    (f8 21 ff 81|81 ff 21 f8)       stdu    r1,-128\(r1\)
+.*:    (f8 41 00 28|28 00 41 f8)       std     r2,40\(r1\)
+.*:    (e9 82 80 70|70 80 82 e9)       ld      r12,-32656\(r2\)
+.*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*:    (e8 42 80 78|78 80 42 e8)       ld      r2,-32648\(r2\)
+.*:    (4e 80 04 21|21 04 80 4e)       bctrl
+.*:    (e8 41 00 28|28 00 41 e8)       ld      r2,40\(r1\)
+.*:    (e8 81 00 38|38 00 81 e8)       ld      r4,56\(r1\)
+.*:    (e8 a1 00 40|40 00 a1 e8)       ld      r5,64\(r1\)
+.*:    (e8 c1 00 48|48 00 c1 e8)       ld      r6,72\(r1\)
+.*:    (e8 e1 00 50|50 00 e1 e8)       ld      r7,80\(r1\)
+.*:    (e9 01 00 58|58 00 01 e9)       ld      r8,88\(r1\)
+.*:    (e9 21 00 60|60 00 21 e9)       ld      r9,96\(r1\)
+.*:    (e9 41 00 68|68 00 41 e9)       ld      r10,104\(r1\)
+.*:    (e9 61 00 70|70 00 61 e9)       ld      r11,112\(r1\)
+.*:    (38 21 00 80|80 00 21 38)       addi    r1,r1,128
+.*:    (e8 01 00 10|10 00 01 e8)       ld      r0,16\(r1\)
+.*:    (7c 08 03 a6|a6 03 08 7c)       mtlr    r0
+.*:    (4e 80 00 20|20 00 80 4e)       blr
+
+.* <\._start>:
+.*:    (38 62 80 08|08 80 62 38)       addi    r3,r2,-32760
+.*:    (4b ff ff 6d|6d ff ff 4b)       bl      .*
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (38 62 80 18|18 80 62 38)       addi    r3,r2,-32744
+.*:    (4b ff ff 61|61 ff ff 4b)       bl      .*
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (38 62 80 28|28 80 62 38)       addi    r3,r2,-32728
+.*:    (4b ff ff 55|55 ff ff 4b)       bl      .*
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (38 62 80 38|38 80 62 38)       addi    r3,r2,-32712
+.*:    (4b ff ff 49|49 ff ff 4b)       bl      .*
+.*:    (60 00 00 00|00 00 00 60)       nop
+.*:    (39 23 80 40|40 80 23 39)       addi    r9,r3,-32704
+.*:    (3d 23 00 00|00 00 23 3d)       addis   r9,r3,0
+.*:    (81 49 80 48|48 80 49 81)       lwz     r10,-32696\(r9\)
+.*:    (e9 22 80 48|48 80 22 e9)       ld      r9,-32696\(r2\)
+.*:    (7d 49 18 2a|2a 18 49 7d)       ldx     r10,r9,r3
+.*:    (e9 22 80 50|50 80 22 e9)       ld      r9,-32688\(r2\)
+.*:    (7d 49 6a 2e|2e 6a 49 7d)       lhzx    r10,r9,r13
+.*:    (89 4d 90 60|60 90 4d 89)       lbz     r10,-28576\(r13\)
+.*:    (3d 2d 00 00|00 00 2d 3d)       addis   r9,r13,0
+.*:    (99 49 90 68|68 90 49 99)       stb     r10,-28568\(r9\)
+.*:    (00 00 00 00|a0 02 01 00)       .*
+.*:    (00 01 02 a0|00 00 00 00)       .*
+
+.* <__glink_PLTresolve>:
+.*:    (7d 88 02 a6|a6 02 88 7d)       mflr    r12
+.*:    (42 9f 00 05|05 00 9f 42)       bcl     .*
+.*:    (7d 68 02 a6|a6 02 68 7d)       mflr    r11
+.*:    (e8 4b ff f0|f0 ff 4b e8)       ld      r2,-16\(r11\)
+.*:    (7d 88 03 a6|a6 03 88 7d)       mtlr    r12
+.*:    (7d 62 5a 14|14 5a 62 7d)       add     r11,r2,r11
+.*:    (e9 8b 00 00|00 00 8b e9)       ld      r12,0\(r11\)
+.*:    (e8 4b 00 08|08 00 4b e8)       ld      r2,8\(r11\)
+.*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*:    (e9 6b 00 10|10 00 6b e9)       ld      r11,16\(r11\)
+.*:    (4e 80 04 20|20 04 80 4e)       bctr
+
+.* <__tls_get_addr_opt@plt>:
+.*:    (38 00 00 00|00 00 00 38)       li      r0,0
+.*:    (4b ff ff d0|d0 ff ff 4b)       b       .* <__glink_PLTresolve>
diff --git a/ld/testsuite/ld-powerpc/tlsexetocrs.d b/ld/testsuite/ld-powerpc/tlsexetocrs.d
new file mode 100644 (file)
index 0000000..4adf305
--- /dev/null
@@ -0,0 +1,88 @@
+#source: tlstoc.s
+#as: -a64
+#ld: tmpdir/libtlslib.so
+#objdump: -dr
+#target: powerpc64*-*-*
+
+.*
+
+Disassembly of section \.text:
+
+.* <.*plt_call\.__tls_get_addr(|_opt)>:
+.*     (e8 03 00 00|00 00 03 e8)       ld      r0,0\(r3\)
+.*     (e9 83 00 08|08 00 83 e9)       ld      r12,8\(r3\)
+.*     (2c 20 00 00|00 00 20 2c)       cmpdi   r0,0
+.*     (7c 60 1b 78|78 1b 60 7c)       mr      r0,r3
+.*     (7c 6c 6a 14|14 6a 6c 7c)       add     r3,r12,r13
+.*     (4d 82 00 20|20 00 82 4d)       beqlr *
+.*     (7c 03 03 78|78 03 03 7c)       mr      r3,r0
+.*     (7c 08 02 a6|a6 02 08 7c)       mflr    r0
+.*     (f8 01 00 10|10 00 01 f8)       std     r0,16\(r1\)
+.*     (f8 81 ff b8|b8 ff 81 f8)       std     r4,-72\(r1\)
+.*     (f8 a1 ff c0|c0 ff a1 f8)       std     r5,-64\(r1\)
+.*     (f8 c1 ff c8|c8 ff c1 f8)       std     r6,-56\(r1\)
+.*     (f8 e1 ff d0|d0 ff e1 f8)       std     r7,-48\(r1\)
+.*     (f9 01 ff d8|d8 ff 01 f9)       std     r8,-40\(r1\)
+.*     (f9 21 ff e0|e0 ff 21 f9)       std     r9,-32\(r1\)
+.*     (f9 41 ff e8|e8 ff 41 f9)       std     r10,-24\(r1\)
+.*     (f9 61 ff f0|f0 ff 61 f9)       std     r11,-16\(r1\)
+.*     (f8 21 ff 81|81 ff 21 f8)       stdu    r1,-128\(r1\)
+.*     (f8 41 00 28|28 00 41 f8)       std     r2,40\(r1\)
+.*     (e9 82 80 70|70 80 82 e9)       ld      r12,-32656\(r2\)
+.*     (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*     (e8 42 80 78|78 80 42 e8)       ld      r2,-32648\(r2\)
+.*     (4e 80 04 21|21 04 80 4e)       bctrl
+.*     (e8 41 00 28|28 00 41 e8)       ld      r2,40\(r1\)
+.*     (e8 81 00 38|38 00 81 e8)       ld      r4,56\(r1\)
+.*     (e8 a1 00 40|40 00 a1 e8)       ld      r5,64\(r1\)
+.*     (e8 c1 00 48|48 00 c1 e8)       ld      r6,72\(r1\)
+.*     (e8 e1 00 50|50 00 e1 e8)       ld      r7,80\(r1\)
+.*     (e9 01 00 58|58 00 01 e9)       ld      r8,88\(r1\)
+.*     (e9 21 00 60|60 00 21 e9)       ld      r9,96\(r1\)
+.*     (e9 41 00 68|68 00 41 e9)       ld      r10,104\(r1\)
+.*     (e9 61 00 70|70 00 61 e9)       ld      r11,112\(r1\)
+.*     (38 21 00 80|80 00 21 38)       addi    r1,r1,128
+.*     (e8 01 00 10|10 00 01 e8)       ld      r0,16\(r1\)
+.*     (7c 08 03 a6|a6 03 08 7c)       mtlr    r0
+.*     (4e 80 00 20|20 00 80 4e)       blr
+
+.* <\._start>:
+.*     (38 62 80 08|08 80 62 38)       addi    r3,r2,-32760
+.*     (4b ff ff 6d|6d ff ff 4b)       bl      .*
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (38 62 80 18|18 80 62 38)       addi    r3,r2,-32744
+.*     (4b ff ff 61|61 ff ff 4b)       bl      .*
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (38 6d 90 38|38 90 6d 38)       addi    r3,r13,-28616
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (38 6d 10 00|00 10 6d 38)       addi    r3,r13,4096
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (39 23 80 40|40 80 23 39)       addi    r9,r3,-32704
+.*     (3d 23 00 00|00 00 23 3d)       addis   r9,r3,0
+.*     (81 49 80 48|48 80 49 81)       lwz     r10,-32696\(r9\)
+.*     (e9 22 80 48|48 80 22 e9)       ld      r9,-32696\(r2\)
+.*     (7d 49 18 2a|2a 18 49 7d)       ldx     r10,r9,r3
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (a1 4d 90 58|58 90 4d a1)       lhz     r10,-28584\(r13\)
+.*     (89 4d 90 60|60 90 4d 89)       lbz     r10,-28576\(r13\)
+.*     (60 00 00 00|00 00 00 60)       nop
+.*     (99 4d 90 68|68 90 4d 99)       stb     r10,-28568\(r13\)
+.*     (00 00 00 00|a0 02 01 00) .*
+.*     (00 01 02 a0|00 00 00 00) .*
+.* <__glink_PLTresolve>:
+.*     (7d 88 02 a6|a6 02 88 7d)       mflr    r12
+.*     (42 9f 00 05|05 00 9f 42)       bcl     20,4\*cr7\+so,.*
+.*     (7d 68 02 a6|a6 02 68 7d)       mflr    r11
+.*     (e8 4b ff f0|f0 ff 4b e8)       ld      r2,-16\(r11\)
+.*     (7d 88 03 a6|a6 03 88 7d)       mtlr    r12
+.*     (7d 62 5a 14|14 5a 62 7d)       add     r11,r2,r11
+.*     (e9 8b 00 00|00 00 8b e9)       ld      r12,0\(r11\)
+.*     (e8 4b 00 08|08 00 4b e8)       ld      r2,8\(r11\)
+.*     (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*     (e9 6b 00 10|10 00 6b e9)       ld      r11,16\(r11\)
+.*     (4e 80 04 20|20 04 80 4e)       bctr
+.* <__tls_get_addr_opt@plt>:
+.*     (38 00 00 00|00 00 00 38)       li      r0,0
+.*     (4b ff ff d0|d0 ff ff 4b)       b       .*
diff --git a/ld/testsuite/ld-powerpc/tlsexetocrs.r b/ld/testsuite/ld-powerpc/tlsexetocrs.r
new file mode 100644 (file)
index 0000000..96ada16
--- /dev/null
@@ -0,0 +1,113 @@
+#source: tlslib.s
+#source: tlstoc.s
+#as: -a64
+#ld:
+#readelf: -WSsrl
+#target: powerpc64*-*-*
+
+There are [0-9]+ section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+ +\[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+ +\[[ 0-9]+\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+ +\[[ 0-9]+\] \.interp +.*
+ +\[[ 0-9]+\] \.hash +.*
+ +\[[ 0-9]+\] \.dynsym +.*
+ +\[[ 0-9]+\] \.dynstr +.*
+ +\[[ 0-9]+\] \.rela\.dyn +.*
+ +\[[ 0-9]+\] \.rela\.plt +.*
+ +\[[ 0-9]+\] \.text +PROGBITS .* 0+124 0+ +AX +0 +0 +32
+ +\[[ 0-9]+\] \.tdata +PROGBITS .* 0+38 0+ WAT +0 +0 +8
+ +\[[ 0-9]+\] \.tbss +NOBITS .* 0+38 0+ WAT +0 +0 +8
+ +\[[ 0-9]+\] \.dynamic +DYNAMIC .* 0+160 10 +WA +4 +0 +8
+ +\[[ 0-9]+\] \.opd .*
+ +\[[ 0-9]+\] \.got +PROGBITS .* 0+58 08 +WA +0 +0 +256
+ +\[[ 0-9]+\] \.plt +.*
+ +\[[ 0-9]+\] \.symtab +.*
+ +\[[ 0-9]+\] \.strtab +.*
+ +\[[ 0-9]+\] \.shstrtab +.*
+#...
+
+Elf file type is EXEC \(Executable file\)
+Entry point .*
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+ +Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+ +PHDR +0x0+40 0x0+10000040 0x0+10000040 0x0+150 0x0+150 R +0x8
+ +INTERP +0x0+190 0x0+10000190 0x0+10000190 0x0+11 0x0+11 R +0x1
+ +\[Requesting program interpreter: .*\]
+ +LOAD .* R E 0x10000
+ +LOAD .* RW +0x10000
+ +DYNAMIC .* RW +0x8
+ +TLS .* 0x0+38 0x0+70 R +0x8
+
+ Section to Segment mapping:
+ +Segment Sections\.\.\.
+ +0+ +
+ +01 +\.interp *
+ +02 +\.interp \.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text *
+ +03 +\.tdata \.dynamic \.opd \.got \.plt *
+ +04 +\.dynamic *
+ +05 +\.tdata \.tbss *
+
+Relocation section '\.rela\.dyn' at offset .* contains 3 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-f ]+R_PPC64_DTPMOD64 +0+ gd \+ 0
+[0-9a-f ]+R_PPC64_DTPREL64 +0+ gd \+ 0
+[0-9a-f ]+R_PPC64_DTPMOD64 +0+ ld \+ 0
+
+Relocation section '\.rela\.plt' at offset .* contains 1 entry:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-f ]+R_PPC64_JMP_SLOT +0+ __tls_get_addr_opt \+ 0
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+.* NOTYPE +LOCAL +DEFAULT +UND *
+.* TLS +GLOBAL +DEFAULT +UND gd
+.* TLS +GLOBAL +DEFAULT +UND ld
+.* FUNC +GLOBAL +DEFAULT +UND __tls_get_addr_opt
+
+Symbol table '\.symtab' contains [0-9]+ entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+.* NOTYPE +LOCAL +DEFAULT +UND *
+.* SECTION +LOCAL +DEFAULT +1 *
+.* SECTION +LOCAL +DEFAULT +2 *
+.* SECTION +LOCAL +DEFAULT +3 *
+.* SECTION +LOCAL +DEFAULT +4 *
+.* SECTION +LOCAL +DEFAULT +5 *
+.* SECTION +LOCAL +DEFAULT +6 *
+.* SECTION +LOCAL +DEFAULT +7 *
+.* SECTION +LOCAL +DEFAULT +8 *
+.* SECTION +LOCAL +DEFAULT +9 *
+.* SECTION +LOCAL +DEFAULT +10 *
+.* SECTION +LOCAL +DEFAULT +11 *
+.* SECTION +LOCAL +DEFAULT +12 *
+.* SECTION +LOCAL +DEFAULT +13 *
+.* FILE +LOCAL +DEFAULT +ABS .*
+.* TLS +LOCAL +DEFAULT +8 gd4
+.* TLS +LOCAL +DEFAULT +8 ld4
+.* TLS +LOCAL +DEFAULT +8 ld5
+.* TLS +LOCAL +DEFAULT +8 ld6
+.* TLS +LOCAL +DEFAULT +8 ie4
+.* TLS +LOCAL +DEFAULT +8 le4
+.* TLS +LOCAL +DEFAULT +8 le5
+.* NOTYPE +LOCAL +DEFAULT +12 \.Lie0
+.* FILE +LOCAL +DEFAULT +ABS 
+.* OBJECT +LOCAL +DEFAULT +10 _DYNAMIC
+.* NOTYPE +LOCAL +DEFAULT +7 __glink_PLTresolve
+.* NOTYPE +LOCAL +DEFAULT +7 .*\.plt_call\.__tls_get_addr(|_opt)
+.* TLS +GLOBAL +DEFAULT +UND gd
+.* TLS +GLOBAL +DEFAULT +9 le0
+.* TLS +GLOBAL +DEFAULT +9 ld0
+.* TLS +GLOBAL +DEFAULT +9 le1
+.* TLS +GLOBAL +DEFAULT +UND ld
+.* FUNC +GLOBAL +DEFAULT +11 _start
+.* TLS +GLOBAL +DEFAULT +9 ld2
+.* TLS +GLOBAL +DEFAULT +9 ld1
+.* NOTYPE +GLOBAL +DEFAULT +13 __bss_start
+.* FUNC +GLOBAL +DEFAULT +UND __tls_get_addr_opt
+.* NOTYPE +GLOBAL +DEFAULT +13 _edata
+.* NOTYPE +GLOBAL +DEFAULT +13 _end
+.* TLS +GLOBAL +DEFAULT +9 gd0
+.* TLS +GLOBAL +DEFAULT +9 ie0
diff --git a/ld/testsuite/ld-powerpc/tlsopt6.d b/ld/testsuite/ld-powerpc/tlsopt6.d
new file mode 100644 (file)
index 0000000..4100302
--- /dev/null
@@ -0,0 +1,86 @@
+#source: tlsopt5.s
+#as: -a64
+#ld: -shared --gc-sections --no-plt-localentry tlsdll.so
+#objdump: -dr
+#target: powerpc64*-*-*
+
+.*
+
+Disassembly of section \.text:
+
+.* <.*\.plt_call\.foo>:
+.*:    (18 00 41 f8|f8 41 00 18)       std     r2,24\(r1\)
+.*:    (28 80 82 e9|e9 82 80 28)       ld      r12,-32728\(r2\)
+.*:    (a6 03 89 7d|7d 89 03 a6)       mtctr   r12
+.*:    (20 04 80 4e|4e 80 04 20)       bctr
+       \.\.\.
+
+.* <.*\.plt_call\.__tls_get_addr_opt@@GLIBC_2\.22>:
+.*:    (00 00 03 e8|e8 03 00 00)       ld      r0,0\(r3\)
+.*:    (08 00 83 e9|e9 83 00 08)       ld      r12,8\(r3\)
+.*:    (00 00 20 2c|2c 20 00 00)       cmpdi   r0,0
+.*:    (78 1b 60 7c|7c 60 1b 78)       mr      r0,r3
+.*:    (14 6a 6c 7c|7c 6c 6a 14)       add     r3,r12,r13
+.*:    (20 00 82 4d|4d 82 00 20)       beqlr *
+.*:    (78 03 03 7c|7c 03 03 78)       mr      r3,r0
+.*:    (a6 02 08 7c|7c 08 02 a6)       mflr    r0
+.*:    (10 00 01 f8|f8 01 00 10)       std     r0,16\(r1\)
+.*:    (c0 ff 81 f8|f8 81 ff c0)       std     r4,-64\(r1\)
+.*:    (c8 ff a1 f8|f8 a1 ff c8)       std     r5,-56\(r1\)
+.*:    (d0 ff c1 f8|f8 c1 ff d0)       std     r6,-48\(r1\)
+.*:    (d8 ff e1 f8|f8 e1 ff d8)       std     r7,-40\(r1\)
+.*:    (e0 ff 01 f9|f9 01 ff e0)       std     r8,-32\(r1\)
+.*:    (e8 ff 21 f9|f9 21 ff e8)       std     r9,-24\(r1\)
+.*:    (f0 ff 41 f9|f9 41 ff f0)       std     r10,-16\(r1\)
+.*:    (f8 ff 61 f9|f9 61 ff f8)       std     r11,-8\(r1\)
+.*:    (a1 ff 21 f8|f8 21 ff a1)       stdu    r1,-96\(r1\)
+.*:    (18 00 41 f8|f8 41 00 18)       std     r2,24\(r1\)
+.*:    (30 80 82 e9|e9 82 80 30)       ld      r12,-32720\(r2\)
+.*:    (a6 03 89 7d|7d 89 03 a6)       mtctr   r12
+.*:    (21 04 80 4e|4e 80 04 21)       bctrl
+.*:    (18 00 41 e8|e8 41 00 18)       ld      r2,24\(r1\)
+.*:    (20 00 81 e8|e8 81 00 20)       ld      r4,32\(r1\)
+.*:    (28 00 a1 e8|e8 a1 00 28)       ld      r5,40\(r1\)
+.*:    (30 00 c1 e8|e8 c1 00 30)       ld      r6,48\(r1\)
+.*:    (38 00 e1 e8|e8 e1 00 38)       ld      r7,56\(r1\)
+.*:    (40 00 01 e9|e9 01 00 40)       ld      r8,64\(r1\)
+.*:    (48 00 21 e9|e9 21 00 48)       ld      r9,72\(r1\)
+.*:    (50 00 41 e9|e9 41 00 50)       ld      r10,80\(r1\)
+.*:    (58 00 61 e9|e9 61 00 58)       ld      r11,88\(r1\)
+.*:    (60 00 21 38|38 21 00 60)       addi    r1,r1,96
+.*:    (10 00 01 e8|e8 01 00 10)       ld      r0,16\(r1\)
+.*:    (a6 03 08 7c|7c 08 03 a6)       mtlr    r0
+.*:    (20 00 80 4e|4e 80 00 20)       blr
+       \.\.\.
+
+.* <_start>:
+.*:    (08 80 62 38|38 62 80 08)       addi    r3,r2,-32760
+.*:    (5d ff ff 4b|4b ff ff 5d)       bl      .* <.*\.plt_call\.__tls_get_addr_opt@@GLIBC_2\.22>
+.*:    (00 00 00 60|60 00 00 00)       nop
+.*:    (35 ff ff 4b|4b ff ff 35)       bl      .* <.*\.plt_call\.foo>
+.*:    (18 00 41 e8|e8 41 00 18)       ld      r2,24\(r1\)
+.*:    (00 00 00 60|60 00 00 00)       nop
+.*
+.*
+
+.* <__glink_PLTresolve>:
+.*:    (a6 02 08 7c|7c 08 02 a6)       mflr    r0
+.*:    (05 00 9f 42|42 9f 00 05)       bcl     .*
+.*:    (a6 02 68 7d|7d 68 02 a6)       mflr    r11
+.*:    (18 00 41 f8|f8 41 00 18)       std     r2,24\(r1\)
+.*:    (f0 ff 4b e8|e8 4b ff f0)       ld      r2,-16\(r11\)
+.*:    (a6 03 08 7c|7c 08 03 a6)       mtlr    r0
+.*:    (50 60 8b 7d|7d 8b 60 50)       subf    r12,r11,r12
+.*:    (14 5a 62 7d|7d 62 5a 14)       add     r11,r2,r11
+.*:    (d0 ff 0c 38|38 0c ff d0)       addi    r0,r12,-48
+.*:    (00 00 8b e9|e9 8b 00 00)       ld      r12,0\(r11\)
+.*:    (82 f0 00 78|78 00 f0 82)       rldicl  r0,r0,62,2
+.*:    (a6 03 89 7d|7d 89 03 a6)       mtctr   r12
+.*:    (08 00 6b e9|e9 6b 00 08)       ld      r11,8\(r11\)
+.*:    (20 04 80 4e|4e 80 04 20)       bctr
+
+.* <foo@plt>:
+.*     (c8 ff ff 4b|4b ff ff c8)       b       .*
+
+.* <__tls_get_addr_opt@plt>:
+.*:    (c4 ff ff 4b|4b ff ff c4)       b       .*
diff --git a/ld/testsuite/ld-powerpc/tlsopt6.wf b/ld/testsuite/ld-powerpc/tlsopt6.wf
new file mode 100644 (file)
index 0000000..abb414a
--- /dev/null
@@ -0,0 +1,49 @@
+Contents of the \.eh_frame section:
+
+0+ 0+10 0+ CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 4
+  Data alignment factor: -8
+  Return address column: 65
+  Augmentation data:     1b
+  DW_CFA_def_cfa: r1 ofs 0
+
+0+14 0+34 0+18 FDE cie=0+ pc=.*
+  DW_CFA_advance_loc: 104 to .*
+  DW_CFA_def_cfa_offset: 96
+  DW_CFA_offset_extended_sf: r65 at cfa\+16
+  DW_CFA_offset: r4 at cfa-64
+  DW_CFA_offset: r5 at cfa-56
+  DW_CFA_offset: r6 at cfa-48
+  DW_CFA_offset: r7 at cfa-40
+  DW_CFA_offset: r8 at cfa-32
+  DW_CFA_offset: r9 at cfa-24
+  DW_CFA_offset: r10 at cfa-16
+  DW_CFA_offset: r11 at cfa-8
+  DW_CFA_advance_loc: 56 to .*
+  DW_CFA_def_cfa_offset: 0
+  DW_CFA_restore: r4
+  DW_CFA_restore: r5
+  DW_CFA_restore: r6
+  DW_CFA_restore: r7
+  DW_CFA_restore: r8
+  DW_CFA_restore: r9
+  DW_CFA_restore: r10
+  DW_CFA_restore: r11
+  DW_CFA_advance_loc: 8 to .*
+  DW_CFA_restore_extended: r65
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+0+4c 0+14 0+50 FDE cie=0+ pc=.*
+  DW_CFA_advance_loc: 4 to .*
+  DW_CFA_register: r65 in r0
+  DW_CFA_advance_loc: 28 to .*
+  DW_CFA_restore_extended: r65
+
+0+64 0+10 0+68 FDE cie=0+ pc=.*
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop