OSDN Git Service

include/elf/
authorAlan Modra <amodra@bigpond.net.au>
Mon, 21 Sep 2009 11:51:02 +0000 (11:51 +0000)
committerAlan Modra <amodra@bigpond.net.au>
Mon, 21 Sep 2009 11:51:02 +0000 (11:51 +0000)
* ppc.h (DT_PPC_TLSOPT): Define.
* ppc64.h (DT_PPC64_TLSOPT): Define.
bfd/
* elf32-ppc.c (TLS_GET_ADDR_GLINK_SIZE): Define.
(ADD_3_12_2, BEQLR, CMPWI_11_0, LWZ_11_3, LWZ_12_3): Define.
(MR_0_3, MR_3_0): Define.
(struct ppc_elf_link_hash_table): Add no_tls_get_addr_opt.
(ppc_elf_select_plt_layout): Save emit_stub_syms param earlier.
(ppc_elf_tls_setup): Add no_tls_get_addr_opt param and save to hash
table.  Check for presense of __tls_get_addr_opt
(allocate_dynrelocs): Increase glink entry size for __tls_get_addr.
(ppc_elf_size_dynamic_sections): Add DT_PPC_TLS_OPT tag.
(write_glink_stub): Add param p.
(ppc_elf_relocate_section): Adjust write_glink_stub call.
(ppc_elf_finish_dynamic_symbol): Emit special glink call stub for
__tls_get_addr.
* elf32-ppc.h (ppc_elf_tls_setup): Update prototype.
* elf64-ppc.c (struct ppc_link_hash_table): Add no_tls_get_addr_opt.
(ppc64_elf_tls_setup): Add no_tls_get_addr_opt param and save to hash
table.  Check for presense of __tls_get_addr_opt.
(ppc64_elf_size_dynamic_sections): Add DT_PPC64_TLS_OPT tag.
(LD_R11_0R3, LD_R12_0R3, MR_R0_R3, CMPDI_R11_0, ADD_R3_R12_R13,
BEQLR, MR_R3_R0, MFLR_R11, STD_R11_0R1, BCTRL, LD_R11_0R1,
LD_R2_0R1, MTLR_R11): Define.
(build_tls_get_addr_stub): New function.
(ppc_build_one_stub): Call it.
(ppc_size_one_stub): Add extra size for __tls_get_addr stub.
(ppc64_elf_relocate_section): Don't change nop to ld 2,40(1) for
__tls_get_addr plt call.
* elf64-ppc.h (ppc64_elf_tls_setup): Update prototype.
binutils/
* readelf.c (get_ppc_dynamic_type): Add TLSOPT.
(get_ppc64_dynamic_type): Likewise.
ld/
* emultempl/ppc32elf.em (no_tls_get_addr_opt): New var.
(ppc_before_allocation): Pass to ppc_elf_tls_setup.
(OPTION_NO_TLS_GET_ADDR_OPT): Define.  Redefine other options in
terms of previous option.
(PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS): Add
--no-tls-get-addr-optimize.
(PARSE_AND_LIST_ARGS_CASES): Handle it.
* emultempl/ppc64elf.em (no_tls_get_addr_opt): New var.
(ppc_before_allocation): Pass to ppc64_elf_tls_setup.
(OPTION_NO_TLS_GET_ADDR_OPT): Define.
(PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS): Add
--no-tls-get-addr-optimize.
(PARSE_AND_LIST_ARGS_CASES): Handle it.
ld/testsuite/
* ld-powerpc/tlslib.s: Delete dot-symbol entry syms.  Add
__tls_get_addr_opt.
* ld-powerpc/tlslib32.s: Add __tls_get_addr_opt.
* ld-powerpc/oldtlslib.s: New file, old-abi version of tlslib.s.
* ld-powerpc/powerpc.exp: Build old-abi library and use it in
two new link tests.
* ld-powerpc/tlsexe.d: Update for new __tls_get_addr stub.
* ld-powerpc/tlsexe.g, * ld-powerpc/tlsexe.r, *ld-powerpc/tlsexe32.d,
* ld-powerpc/tlsexe32.g, * ld-powerpc/tlsexe32.r,
* ld-powerpc/tlsexetoc.d, * ld-powerpc/tlsexetoc.g,
* ld-powerpc/tlsexetoc.r: Likewise.

27 files changed:
bfd/ChangeLog
bfd/elf32-ppc.c
bfd/elf32-ppc.h
bfd/elf64-ppc.c
bfd/elf64-ppc.h
binutils/ChangeLog
binutils/readelf.c
include/elf/ChangeLog
include/elf/ppc.h
include/elf/ppc64.h
ld/ChangeLog
ld/emultempl/ppc32elf.em
ld/emultempl/ppc64elf.em
ld/testsuite/ChangeLog
ld/testsuite/ld-powerpc/oldtlslib.s [new file with mode: 0644]
ld/testsuite/ld-powerpc/powerpc.exp
ld/testsuite/ld-powerpc/tlsexe.d
ld/testsuite/ld-powerpc/tlsexe.g
ld/testsuite/ld-powerpc/tlsexe.r
ld/testsuite/ld-powerpc/tlsexe32.d
ld/testsuite/ld-powerpc/tlsexe32.g
ld/testsuite/ld-powerpc/tlsexe32.r
ld/testsuite/ld-powerpc/tlsexetoc.d
ld/testsuite/ld-powerpc/tlsexetoc.g
ld/testsuite/ld-powerpc/tlsexetoc.r
ld/testsuite/ld-powerpc/tlslib.s
ld/testsuite/ld-powerpc/tlslib32.s

index a4f99e7..9900119 100644 (file)
@@ -1,3 +1,33 @@
+2009-09-21  Alan Modra  <amodra@bigpond.net.au>
+
+       * elf32-ppc.c (TLS_GET_ADDR_GLINK_SIZE): Define.
+       (ADD_3_12_2, BEQLR, CMPWI_11_0, LWZ_11_3, LWZ_12_3): Define.
+       (MR_0_3, MR_3_0): Define.
+       (struct ppc_elf_link_hash_table): Add no_tls_get_addr_opt.
+       (ppc_elf_select_plt_layout): Save emit_stub_syms param earlier.
+       (ppc_elf_tls_setup): Add no_tls_get_addr_opt param and save to hash
+       table.  Check for presense of __tls_get_addr_opt
+       (allocate_dynrelocs): Increase glink entry size for __tls_get_addr.
+       (ppc_elf_size_dynamic_sections): Add DT_PPC_TLS_OPT tag.
+       (write_glink_stub): Add param p.
+       (ppc_elf_relocate_section): Adjust write_glink_stub call.
+       (ppc_elf_finish_dynamic_symbol): Emit special glink call stub for
+       __tls_get_addr.
+       * elf32-ppc.h (ppc_elf_tls_setup): Update prototype.
+       * elf64-ppc.c (struct ppc_link_hash_table): Add no_tls_get_addr_opt.
+       (ppc64_elf_tls_setup): Add no_tls_get_addr_opt param and save to hash
+       table.  Check for presense of __tls_get_addr_opt.
+       (ppc64_elf_size_dynamic_sections): Add DT_PPC64_TLS_OPT tag.
+       (LD_R11_0R3, LD_R12_0R3, MR_R0_R3, CMPDI_R11_0, ADD_R3_R12_R13,
+       BEQLR, MR_R3_R0, MFLR_R11, STD_R11_0R1, BCTRL, LD_R11_0R1,
+       LD_R2_0R1, MTLR_R11): Define.
+       (build_tls_get_addr_stub): New function.
+       (ppc_build_one_stub): Call it.
+       (ppc_size_one_stub): Add extra size for __tls_get_addr stub.
+       (ppc64_elf_relocate_section): Don't change nop to ld 2,40(1) for
+       __tls_get_addr plt call.
+       * elf64-ppc.h (ppc64_elf_tls_setup): Update prototype.
+
 2009-09-19  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * elf-bfd.h (eh_cie_fde): Add personality_offset and
index bbe94db..95058a2 100644 (file)
@@ -61,6 +61,7 @@ static bfd_reloc_status_type ppc_elf_unhandled_reloc
 /* For new-style .glink and .plt.  */
 #define GLINK_PLTRESOLVE 16*4
 #define GLINK_ENTRY_SIZE 4*4
+#define TLS_GET_ADDR_GLINK_SIZE 12*4
 
 /* VxWorks uses its own plt layout, filled in by the static linker.  */
 
@@ -135,17 +136,24 @@ static const bfd_vma ppc_elf_vxworks_pic_plt0_entry
 #define ADDIS_12_12    0x3d8c0000
 #define ADDI_11_11     0x396b0000
 #define ADD_0_11_11    0x7c0b5a14
+#define ADD_3_12_2     0x7c6c1214
 #define ADD_11_0_11    0x7d605a14
 #define B              0x48000000
 #define BCL_20_31      0x429f0005
 #define BCTR           0x4e800420
+#define BEQLR          0x4d820020
+#define CMPWI_11_0     0x2c0b0000
 #define LIS_11         0x3d600000
 #define LIS_12         0x3d800000
 #define LWZU_0_12      0x840c0000
 #define LWZ_0_12       0x800c0000
+#define LWZ_11_3       0x81630000
 #define LWZ_11_11      0x816b0000
 #define LWZ_11_30      0x817e0000
+#define LWZ_12_3       0x81830000
 #define LWZ_12_12      0x818c0000
+#define MR_0_3         0x7c601b78
+#define MR_3_0         0x7c030378
 #define MFLR_0         0x7c0802a6
 #define MFLR_12                0x7d8802a6
 #define MTCTR_0                0x7c0903a6
@@ -2754,6 +2762,9 @@ struct ppc_elf_link_hash_table
   /* Set if we should emit symbols for stubs.  */
   unsigned int emit_stub_syms:1;
 
+  /* Set if __tls_get_addr optimization should not be done.  */
+  unsigned int no_tls_get_addr_opt:1;
+
   /* True if the target system is VxWorks.  */
   unsigned int is_vxworks:1;
 
@@ -4277,6 +4288,8 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   htab = ppc_elf_hash_table (info);
 
+  htab->emit_stub_syms = emit_stub_syms;
+
   if (htab->plt_type == PLT_UNSET)
     {
       if (plt_style == PLT_OLD)
@@ -4310,8 +4323,6 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
   if (htab->plt_type == PLT_OLD && plt_style == PLT_NEW)
     info->callbacks->info (_("Using bss-plt due to %B"), htab->old_bfd);
 
-  htab->emit_stub_syms = emit_stub_syms;
-
   BFD_ASSERT (htab->plt_type != PLT_VXWORKS);
 
   if (htab->plt_type == PLT_NEW)
@@ -4539,11 +4550,62 @@ ppc_elf_gc_sweep_hook (bfd *abfd,
    generic ELF tls_setup function.  */
 
 asection *
-ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
+ppc_elf_tls_setup (bfd *obfd,
+                  struct bfd_link_info *info,
+                  int no_tls_get_addr_opt)
 {
   struct ppc_elf_link_hash_table *htab;
 
   htab = ppc_elf_hash_table (info);
+  htab->tls_get_addr = elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
+                                            FALSE, FALSE, TRUE);
+  if (!no_tls_get_addr_opt)
+    {
+      struct elf_link_hash_entry *opt, *tga;
+      opt = elf_link_hash_lookup (&htab->elf, "__tls_get_addr_opt",
+                                 FALSE, FALSE, TRUE);
+      if (opt != NULL
+         && (opt->root.type == bfd_link_hash_defined
+             || opt->root.type == bfd_link_hash_defweak))
+       {
+         /* If glibc supports an optimized __tls_get_addr call stub,
+            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 = htab->tls_get_addr;
+         if (htab->elf.dynamic_sections_created
+             && tga != NULL
+             && (tga->type == STT_FUNC
+                 || tga->needs_plt)
+             && !(SYMBOL_CALLS_LOCAL (info, tga)
+                  || (ELF_ST_VISIBILITY (tga->other) != STV_DEFAULT
+                      && tga->root.type == bfd_link_hash_undefweak)))
+           {
+             struct plt_entry *ent;
+             ent = find_plt_ent (&tga->plt.plist, NULL, 0);
+             if (ent != NULL
+                 && ent->plt.refcount > 0)
+               {
+                 tga->root.type = bfd_link_hash_indirect;
+                 tga->root.u.i.link = &opt->root;
+                 ppc_elf_copy_indirect_symbol (info, opt, tga);
+                 if (opt->dynindx != -1)
+                   {
+                     /* Use __tls_get_addr_opt in dynamic relocations.  */
+                     opt->dynindx = -1;
+                     _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
+                                             opt->dynstr_index);
+                     if (!bfd_elf_link_record_dynamic_symbol (info, opt))
+                       return FALSE;
+                   }
+                 htab->tls_get_addr = opt;
+               }
+           }
+       }
+      else
+       no_tls_get_addr_opt = TRUE;
+    }
+  htab->no_tls_get_addr_opt = no_tls_get_addr_opt;
   if (htab->plt_type == PLT_NEW
       && htab->plt != NULL
       && htab->plt->output_section != NULL)
@@ -4552,8 +4614,6 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
       elf_section_flags (htab->plt->output_section) = SHF_ALLOC + SHF_WRITE;
     }
 
-  htab->tls_get_addr = elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
-                                            FALSE, FALSE, TRUE);
   return _bfd_elf_tls_setup (obfd, info);
 }
 
@@ -5144,6 +5204,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
                      {
                        glink_offset = s->size;
                        s->size += GLINK_ENTRY_SIZE;
+                       if (h == htab->tls_get_addr
+                           && !htab->no_tls_get_addr_opt)
+                         s->size += TLS_GET_ADDR_GLINK_SIZE - GLINK_ENTRY_SIZE;
                      }
                    if (!doneone
                        && !info->shared
@@ -5820,6 +5883,11 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        {
          if (!add_dynamic_entry (DT_PPC_GOT, 0))
            return FALSE;
+         if (!htab->no_tls_get_addr_opt
+             && htab->tls_get_addr != NULL
+             && htab->tls_get_addr->plt.plist != NULL
+             && !add_dynamic_entry (DT_PPC_TLSOPT, 0))
+           return FALSE;
        }
 
       if (relocs)
@@ -6474,18 +6542,16 @@ elf_finish_pointer_linker_section (bfd *input_bfd,
 #define PPC_HA(v) PPC_HI ((v) + 0x8000)
 
 static void
-write_glink_stub (struct plt_entry *ent, asection *plt_sec,
+write_glink_stub (struct plt_entry *ent, asection *plt_sec, unsigned char *p,
                  struct bfd_link_info *info)
 {
   struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
   bfd *output_bfd = info->output_bfd;
   bfd_vma plt;
-  unsigned char *p;
 
   plt = ((ent->plt.offset & ~1)
         + plt_sec->output_section->vma
         + plt_sec->output_offset);
-  p = (unsigned char *) htab->glink->contents + ent->glink_offset;
 
   if (info->shared)
     {
@@ -7045,7 +7111,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
                }
              if (h == NULL && (ent->glink_offset & 1) == 0)
                {
-                 write_glink_stub (ent, htab->iplt, info);
+                 unsigned char *p = ((unsigned char *) htab->glink->contents
+                                     + ent->glink_offset);
+                 write_glink_stub (ent, htab->iplt, p, info);
                  ent->glink_offset |= 1;
                }
 
@@ -8274,12 +8342,35 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
            || !htab->elf.dynamic_sections_created
            || h->dynindx == -1)
          {
+           unsigned char *p;
            asection *splt = htab->plt;
            if (!htab->elf.dynamic_sections_created
                || h->dynindx == -1)
              splt = htab->iplt;
 
-           write_glink_stub (ent, splt, info);
+           p = (unsigned char *) htab->glink->contents + ent->glink_offset;
+
+           if (h == htab->tls_get_addr && !htab->no_tls_get_addr_opt)
+             {
+               bfd_put_32 (output_bfd, LWZ_11_3, p);
+               p += 4;
+               bfd_put_32 (output_bfd, LWZ_12_3 + 4, p);
+               p += 4;
+               bfd_put_32 (output_bfd, MR_0_3, p);
+               p += 4;
+               bfd_put_32 (output_bfd, CMPWI_11_0, p);
+               p += 4;
+               bfd_put_32 (output_bfd, ADD_3_12_2, p);
+               p += 4;
+               bfd_put_32 (output_bfd, BEQLR, p);
+               p += 4;
+               bfd_put_32 (output_bfd, MR_3_0, p);
+               p += 4;
+               bfd_put_32 (output_bfd, NOP, p);
+               p += 4;
+             }
+
+           write_glink_stub (ent, splt, p, info);
 
            if (!info->shared)
              /* We only need one non-PIC glink stub.  */
index ef1f0ac..4becb30 100644 (file)
@@ -28,6 +28,6 @@ enum ppc_elf_plt_type
 
 int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *,
                               enum ppc_elf_plt_type, int);
-asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *);
+asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *, int);
 bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *);
 void ppc_elf_set_sdata_syms (bfd *, struct bfd_link_info *);
index 99bfec2..35757b8 100644 (file)
@@ -3771,6 +3771,9 @@ struct ppc_link_hash_table
   /* Set if we should emit symbols for stubs.  */
   unsigned int emit_stub_syms:1;
 
+  /* Set if __tls_get_addr optimization should not be done.  */
+  unsigned int no_tls_get_addr_opt:1;
+
   /* Support for multiple toc sections.  */
   unsigned int no_multi_toc:1;
   unsigned int multi_toc_needed:1;
@@ -7218,7 +7221,9 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
 /* Set htab->tls_get_addr and call the generic ELF tls_setup function.  */
 
 asection *
-ppc64_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
+ppc64_elf_tls_setup (bfd *obfd,
+                    struct bfd_link_info *info,
+                    int no_tls_get_addr_opt)
 {
   struct ppc_link_hash_table *htab;
 
@@ -7226,9 +7231,83 @@ ppc64_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
   htab->tls_get_addr = ((struct ppc_link_hash_entry *)
                        elf_link_hash_lookup (&htab->elf, ".__tls_get_addr",
                                              FALSE, FALSE, TRUE));
+  /* 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 (!no_tls_get_addr_opt)
+    {
+      struct elf_link_hash_entry *opt, *opt_fd, *tga, *tga_fd;
+
+      opt = elf_link_hash_lookup (&htab->elf, ".__tls_get_addr_opt",
+                                 FALSE, FALSE, TRUE);
+      if (opt != NULL)
+       func_desc_adjust (opt, info);
+      opt_fd = elf_link_hash_lookup (&htab->elf, "__tls_get_addr_opt",
+                                    FALSE, FALSE, TRUE);
+      if (opt_fd != NULL
+         && (opt_fd->root.type == bfd_link_hash_defined
+             || opt_fd->root.type == bfd_link_hash_defweak))
+       {
+         /* If glibc supports an optimized __tls_get_addr call stub,
+            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)
+                  || (ELF_ST_VISIBILITY (tga_fd->other) != STV_DEFAULT
+                      && tga_fd->root.type == bfd_link_hash_undefweak)))
+           {
+             struct plt_entry *ent;
+
+             for (ent = tga_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 (opt_fd->dynindx != -1)
+                   {
+                     /* Use __tls_get_addr_opt in dynamic relocations.  */
+                     opt_fd->dynindx = -1;
+                     _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
+                                             opt_fd->dynstr_index);
+                     if (!bfd_elf_link_record_dynamic_symbol (info, opt_fd))
+                       return FALSE;
+                   }
+                 htab->tls_get_addr_fd = (struct ppc_link_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;
+                     ppc64_elf_copy_indirect_symbol (info, opt, tga);
+                     _bfd_elf_link_hash_hide_symbol (info, opt,
+                                                     tga->forced_local);
+                     htab->tls_get_addr = (struct ppc_link_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;
+                   }
+               }
+           }
+       }
+      else
+       no_tls_get_addr_opt = TRUE;
+    }
+  htab->no_tls_get_addr_opt = no_tls_get_addr_opt;
   return _bfd_elf_tls_setup (obfd, info);
 }
 
@@ -8666,6 +8745,12 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
            return FALSE;
        }
 
+      if (!htab->no_tls_get_addr_opt
+         && htab->tls_get_addr_fd != NULL
+         && htab->tls_get_addr_fd->elf.plt.plist != NULL
+         && !add_dynamic_entry (DT_PPC64_TLSOPT, 0))
+       return FALSE;
+
       if (relocs)
        {
          if (!add_dynamic_entry (DT_RELA, 0)
@@ -8859,6 +8944,49 @@ build_plt_stub (bfd *obfd, bfd_byte *p, int offset, Elf_Internal_Rela *r)
   return p;
 }
 
+/* Build a special .plt call stub for __tls_get_addr.  */
+
+#define LD_R11_0R3     0xe9630000
+#define LD_R12_0R3     0xe9830000
+#define MR_R0_R3       0x7c601b78
+#define CMPDI_R11_0    0x2c2b0000
+#define ADD_R3_R12_R13 0x7c6c6a14
+#define BEQLR          0x4d820020
+#define MR_R3_R0       0x7c030378
+#define MFLR_R11       0x7d6802a6
+#define STD_R11_0R1    0xf9610000
+#define BCTRL          0x4e800421
+#define LD_R11_0R1     0xe9610000
+#define LD_R2_0R1      0xe8410000
+#define MTLR_R11       0x7d6803a6
+
+static inline bfd_byte *
+build_tls_get_addr_stub (bfd *obfd, bfd_byte *p, int offset,
+                        Elf_Internal_Rela *r)
+{
+  bfd_put_32 (obfd, LD_R11_0R3 + 0, p),                p += 4;
+  bfd_put_32 (obfd, LD_R12_0R3 + 8, p),                p += 4;
+  bfd_put_32 (obfd, MR_R0_R3, p),              p += 4;
+  bfd_put_32 (obfd, CMPDI_R11_0, p),           p += 4;
+  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;
+  bfd_put_32 (obfd, MFLR_R11, p),              p += 4;
+  bfd_put_32 (obfd, STD_R11_0R1 + 32, p),      p += 4;
+
+  if (r != NULL)
+    r[0].r_offset += 9 * 4;
+  p = build_plt_stub (obfd, p, offset, r);
+  bfd_put_32 (obfd, BCTRL, p - 4);
+
+  bfd_put_32 (obfd, LD_R11_0R1 + 32, p),       p += 4;
+  bfd_put_32 (obfd, LD_R2_0R1 + 40, p),                p += 4;
+  bfd_put_32 (obfd, MTLR_R11, p),              p += 4;
+  bfd_put_32 (obfd, BLR, p),                   p += 4;
+
+  return p;
+}
+
 static Elf_Internal_Rela *
 get_relocs (asection *sec, int count)
 {
@@ -9227,7 +9355,13 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
            r[0].r_offset += 2;
          r[0].r_addend = dest;
        }
-      p = build_plt_stub (htab->stub_bfd, loc, off, r);
+      if (stub_entry->h != NULL
+         && (stub_entry->h == htab->tls_get_addr_fd
+             || stub_entry->h == htab->tls_get_addr)
+         && !htab->no_tls_get_addr_opt)
+       p = build_tls_get_addr_stub (htab->stub_bfd, loc, off, r);
+      else
+       p = build_plt_stub (htab->stub_bfd, loc, off, r);
       size = p - loc;
       break;
 
@@ -9316,6 +9450,11 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
        size -= 4;
       if (PPC_HA (off + 16) != PPC_HA (off))
        size += 4;
+      if (stub_entry->h != NULL
+         && (stub_entry->h == htab->tls_get_addr_fd
+             || stub_entry->h == htab->tls_get_addr)
+         && !htab->no_tls_get_addr_opt)
+       size += 13 * 4;
       if (info->emitrelocations)
        {
          stub_entry->stub_sec->reloc_count
@@ -11255,8 +11394,16 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                  if (nop == NOP
                      || nop == CROR_151515 || nop == CROR_313131)
                    {
-                     bfd_put_32 (input_bfd, LD_R2_40R1,
-                                 contents + rel->r_offset + 4);
+                     if (h != NULL
+                         && (h == htab->tls_get_addr_fd
+                             || h == htab->tls_get_addr)
+                         && !htab->no_tls_get_addr_opt)
+                       {
+                         /* Special stub used, leave nop alone.  */
+                       }
+                     else
+                       bfd_put_32 (input_bfd, LD_R2_40R1,
+                                   contents + rel->r_offset + 4);
                      can_plt_call = TRUE;
                    }
                }
index 687b4a1..e5f7140 100644 (file)
@@ -24,7 +24,7 @@ void ppc64_elf_init_stub_bfd
 bfd_boolean ppc64_elf_edit_opd
   (bfd *, struct bfd_link_info *, bfd_boolean);
 asection *ppc64_elf_tls_setup
-  (bfd *, struct bfd_link_info *);
+(bfd *, struct bfd_link_info *, int);
 bfd_boolean ppc64_elf_tls_optimize
   (bfd *, struct bfd_link_info *);
 bfd_boolean ppc64_elf_edit_toc
index f03ccf0..e049c1d 100644 (file)
@@ -1,3 +1,8 @@
+2009-09-21  Alan Modra  <amodra@bigpond.net.au>
+
+       * readelf.c (get_ppc_dynamic_type): Add TLSOPT.
+       (get_ppc64_dynamic_type): Likewise.
+
 2009-09-18  Nick Clifton  <nickc@redhat.com>
 
        * po/es.po: Updated Spanish translation.
index 64630f5..c20c84a 100644 (file)
@@ -1470,7 +1470,8 @@ get_ppc_dynamic_type (unsigned long type)
 {
   switch (type)
     {
-    case DT_PPC_GOT: return "PPC_GOT";
+    case DT_PPC_GOT:    return "PPC_GOT";
+    case DT_PPC_TLSOPT: return "PPC_TLSOPT";
     default:
       return NULL;
     }
@@ -1481,9 +1482,10 @@ get_ppc64_dynamic_type (unsigned long type)
 {
   switch (type)
     {
-    case DT_PPC64_GLINK: return "PPC64_GLINK";
-    case DT_PPC64_OPD:   return "PPC64_OPD";
-    case DT_PPC64_OPDSZ: return "PPC64_OPDSZ";
+    case DT_PPC64_GLINK:  return "PPC64_GLINK";
+    case DT_PPC64_OPD:    return "PPC64_OPD";
+    case DT_PPC64_OPDSZ:  return "PPC64_OPDSZ";
+    case DT_PPC64_TLSOPT: return "PPC64_TLSOPT";
     default:
       return NULL;
     }
index b7df2ac..a33fb84 100644 (file)
@@ -1,3 +1,8 @@
+2009-09-21  Alan Modra  <amodra@bigpond.net.au>
+
+       * ppc.h (DT_PPC_TLSOPT): Define.
+       * ppc64.h (DT_PPC64_TLSOPT): Define.
+
 2009-08-10  Daniel Gutson  <dgutson@codesourcery.com>
 
        * arm.h: (SHT_ARM_DEBUGOVERLAY): New define.
index 14c643a..e2de0ad 100644 (file)
@@ -153,7 +153,10 @@ END_RELOC_NUMBERS (R_PPC_max)
   ((R) >= R_PPC_TLS && (R) <= R_PPC_GOT_DTPREL16_HA)
 
 /* Specify the value of _GLOBAL_OFFSET_TABLE_.  */
-#define DT_PPC_GOT             DT_LOPROC
+#define DT_PPC_GOT             (DT_LOPROC)
+
+/* Specify that tls descriptors should be optimized.  */
+#define DT_PPC_TLSOPT          (DT_LOPROC + 1)
 
 /* Processor specific flags for the ELF header e_flags field.  */
 
index da54f3f..04ddcd9 100644 (file)
@@ -165,4 +165,7 @@ END_RELOC_NUMBERS (R_PPC64_max)
 #define DT_PPC64_OPD           (DT_LOPROC + 1)
 #define DT_PPC64_OPDSZ         (DT_LOPROC + 2)
 
+/* Specify that tls descriptors should be optimized.  */
+#define DT_PPC64_TLSOPT                (DT_LOPROC + 3)
+
 #endif /* _ELF_PPC64_H */
index 5226599..9c16d6a 100644 (file)
@@ -1,3 +1,19 @@
+2009-09-21  Alan Modra  <amodra@bigpond.net.au>
+
+       * emultempl/ppc32elf.em (no_tls_get_addr_opt): New var.
+       (ppc_before_allocation): Pass to ppc_elf_tls_setup.
+       (OPTION_NO_TLS_GET_ADDR_OPT): Define.  Redefine other options in
+       terms of previous option.
+       (PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS): Add
+       --no-tls-get-addr-optimize.
+       (PARSE_AND_LIST_ARGS_CASES): Handle it.
+       * emultempl/ppc64elf.em (no_tls_get_addr_opt): New var.
+       (ppc_before_allocation): Pass to ppc64_elf_tls_setup.
+       (OPTION_NO_TLS_GET_ADDR_OPT): Define.
+       (PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS): Add
+       --no-tls-get-addr-optimize.
+       (PARSE_AND_LIST_ARGS_CASES): Handle it.
+
 2009-09-18  Nick Clifton  <nickc@redhat.com>
 
        * po/es.po: Updated Spanish translation.
index c54f35c..2295ae9 100644 (file)
@@ -33,6 +33,7 @@ fragment <<EOF
 
 /* Whether to run tls optimization.  */
 static int notlsopt = 0;
+static int no_tls_get_addr_opt = 0;
 
 /* Whether to emit symbols for stubs.  */
 static int emit_stub_syms = 0;
@@ -103,7 +104,9 @@ ppc_before_allocation (void)
 {
   if (is_ppc_elf (link_info.output_bfd))
     {
-      if (ppc_elf_tls_setup (link_info.output_bfd, &link_info) && !notlsopt)
+      if (ppc_elf_tls_setup (link_info.output_bfd, &link_info,
+                            no_tls_get_addr_opt)
+         && !notlsopt)
        {
          if (!ppc_elf_tls_optimize (link_info.output_bfd, &link_info))
            {
@@ -174,15 +177,17 @@ fi
 #
 PARSE_AND_LIST_PROLOGUE='
 #define OPTION_NO_TLS_OPT              301
-#define OPTION_NEW_PLT                 302
-#define OPTION_OLD_PLT                 303
-#define OPTION_OLD_GOT                 304
-#define OPTION_STUBSYMS                        305
+#define OPTION_NO_TLS_GET_ADDR_OPT     (OPTION_NO_TLS_OPT + 1)
+#define OPTION_NEW_PLT                 (OPTION_NO_TLS_GET_ADDR_OPT + 1)
+#define OPTION_OLD_PLT                 (OPTION_NEW_PLT + 1)
+#define OPTION_OLD_GOT                 (OPTION_OLD_PLT + 1)
+#define OPTION_STUBSYMS                        (OPTION_OLD_GOT + 1)
 '
 
 PARSE_AND_LIST_LONGOPTS='
   { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS },
   { "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT },
+  { "no-tls-get-addr-optimize", no_argument, NULL, OPTION_NO_TLS_GET_ADDR_OPT },
   { "secure-plt", no_argument, NULL, OPTION_NEW_PLT },
   { "bss-plt", no_argument, NULL, OPTION_OLD_PLT },
   { "sdata-got", no_argument, NULL, OPTION_OLD_GOT },
@@ -192,6 +197,7 @@ PARSE_AND_LIST_OPTIONS='
   fprintf (file, _("\
   --emit-stub-syms            Label linker stubs with a symbol.\n\
   --no-tls-optimize           Don'\''t try to optimize TLS accesses.\n\
+  --no-tls-get-addr-optimize  Don'\''t use a special __tls_get_addr call.\n\
   --secure-plt                Use new-style PLT if possible.\n\
   --bss-plt                   Force old-style BSS PLT.\n\
   --sdata-got                 Force GOT location just before .sdata.\n"
@@ -207,6 +213,10 @@ PARSE_AND_LIST_ARGS_CASES='
       notlsopt = 1;
       break;
 
+    case OPTION_NO_TLS_GET_ADDR_OPT:
+      no_tls_get_addr_opt = 1;
+      break;
+
     case OPTION_NEW_PLT:
       plt_style = PLT_NEW;
       break;
index 05afbb1..09f0f17 100644 (file)
@@ -47,6 +47,7 @@ static int dotsyms = 1;
 
 /* Whether to run tls optimization.  */
 static int no_tls_opt = 0;
+static int no_tls_get_addr_opt = 0;
 
 /* Whether to run opd optimization.  */
 static int no_opd_opt = 0;
@@ -106,7 +107,8 @@ ppc_before_allocation (void)
                                  non_overlapping_opd))
        einfo ("%X%P: can not edit %s %E\n", "opd");
 
-      if (ppc64_elf_tls_setup (link_info.output_bfd, &link_info)
+      if (ppc64_elf_tls_setup (link_info.output_bfd, &link_info,
+                              no_tls_get_addr_opt)
          && !no_tls_opt)
        {
          /* Size the sections.  This is premature, but we want to know the
@@ -488,7 +490,8 @@ PARSE_AND_LIST_PROLOGUE='
 #define OPTION_DOTSYMS                 (OPTION_STUBSYMS + 1)
 #define OPTION_NO_DOTSYMS              (OPTION_DOTSYMS + 1)
 #define OPTION_NO_TLS_OPT              (OPTION_NO_DOTSYMS + 1)
-#define OPTION_NO_OPD_OPT              (OPTION_NO_TLS_OPT + 1)
+#define OPTION_NO_TLS_GET_ADDR_OPT     (OPTION_NO_TLS_OPT + 1)
+#define OPTION_NO_OPD_OPT              (OPTION_NO_TLS_GET_ADDR_OPT + 1)
 #define OPTION_NO_TOC_OPT              (OPTION_NO_OPD_OPT + 1)
 #define OPTION_NO_MULTI_TOC            (OPTION_NO_TOC_OPT + 1)
 #define OPTION_NON_OVERLAPPING_OPD     (OPTION_NO_MULTI_TOC + 1)
@@ -500,6 +503,7 @@ PARSE_AND_LIST_LONGOPTS='
   { "dotsyms", no_argument, NULL, OPTION_DOTSYMS },
   { "no-dotsyms", no_argument, NULL, OPTION_NO_DOTSYMS },
   { "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT },
+  { "no-tls-get-addr-optimize", no_argument, NULL, OPTION_NO_TLS_GET_ADDR_OPT },
   { "no-opd-optimize", no_argument, NULL, OPTION_NO_OPD_OPT },
   { "no-toc-optimize", no_argument, NULL, OPTION_NO_TOC_OPT },
   { "no-multi-toc", no_argument, NULL, OPTION_NO_MULTI_TOC },
@@ -533,6 +537,9 @@ PARSE_AND_LIST_OPTIONS='
   --no-tls-optimize           Don'\''t try to optimize TLS accesses.\n"
                   ));
   fprintf (file, _("\
+  --no-tls-get-addr-optimize  Don'\''t use a special __tls_get_addr call.\n"
+                  ));
+  fprintf (file, _("\
   --no-opd-optimize           Don'\''t optimize the OPD section.\n"
                   ));
   fprintf (file, _("\
@@ -573,6 +580,10 @@ PARSE_AND_LIST_ARGS_CASES='
       no_tls_opt = 1;
       break;
 
+    case OPTION_NO_TLS_GET_ADDR_OPT:
+      no_tls_get_addr_opt = 1;
+      break;
+
     case OPTION_NO_OPD_OPT:
       no_opd_opt = 1;
       break;
index 8d1b1ec..3185e3b 100644 (file)
@@ -1,3 +1,17 @@
+2009-09-21  Alan Modra  <amodra@bigpond.net.au>
+
+       * ld-powerpc/tlslib.s: Delete dot-symbol entry syms.  Add
+       __tls_get_addr_opt.
+       * ld-powerpc/tlslib32.s: Add __tls_get_addr_opt.
+       * ld-powerpc/oldtlslib.s: New file, old-abi version of tlslib.s.
+       * ld-powerpc/powerpc.exp: Build old-abi library and use it in
+       two new link tests.
+       * ld-powerpc/tlsexe.d: Update for new __tls_get_addr stub.
+       * ld-powerpc/tlsexe.g, * ld-powerpc/tlsexe.r, *ld-powerpc/tlsexe32.d,
+       * ld-powerpc/tlsexe32.g, * ld-powerpc/tlsexe32.r, 
+       * ld-powerpc/tlsexetoc.d, * ld-powerpc/tlsexetoc.g,
+       * ld-powerpc/tlsexetoc.r: Likewise.
+
 2009-09-20  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * ld-mips-elf/elf-rel-got-n64-linux.d: Expect BALs.
diff --git a/ld/testsuite/ld-powerpc/oldtlslib.s b/ld/testsuite/ld-powerpc/oldtlslib.s
new file mode 100644 (file)
index 0000000..5786df1
--- /dev/null
@@ -0,0 +1,29 @@
+       .global __tls_get_addr,__tls_get_addr_opt,gd,ld
+       .global .__tls_get_addr,.__tls_get_addr_opt
+       .type .__tls_get_addr,@function
+       .type .__tls_get_addr_opt,@function
+
+       .section ".opd","aw",@progbits
+__tls_get_addr:
+__tls_get_addr_opt:
+       .align 3
+       .quad   .__tls_get_addr
+       .quad   .TOC.@tocbase
+       .quad   0
+       .size __tls_get_addr,24
+       .size __tls_get_addr_opt,24
+
+       .section ".tbss","awT",@nobits
+       .align 3
+gd:    .space 8
+
+       .section ".tdata","awT",@progbits
+       .align 2
+ld:    .long 0xc0ffee
+
+       .text
+.__tls_get_addr:
+.__tls_get_addr_opt:
+       blr
+       .size .__tls_get_addr,. - .__tls_get_addr
+       .size .__tls_get_addr_opt,. - .__tls_get_addr_opt
index 26eaac7..fce9664 100644 (file)
@@ -138,10 +138,16 @@ set ppc64elftests {
       "tls"}
     {"TLS helper shared library" "-shared -melf64ppc tmpdir/tlslib.o" "" {}
      {} "libtlslib.so"}
+    {"TLS helper old shared lib" "-shared -melf64ppc" "-a64" {oldtlslib.s}
+     {} "liboldlib.so"}
     {"TLS dynamic exec" "-melf64ppc tmpdir/tls.o tmpdir/libtlslib.so" "" {}
      {{readelf -WSsrl tlsexe.r} {objdump -dr tlsexe.d}
       {objdump -sj.got tlsexe.g} {objdump -sj.tdata tlsexe.t}}
       "tlsexe"}
+    {"TLS dynamic old" "-melf64ppc tmpdir/tls.o tmpdir/liboldlib.so" "" {}
+     {{readelf -WSsrl tlsexe.r} {objdump -dr tlsexe.d}
+      {objdump -sj.got tlsexe.g} {objdump -sj.tdata tlsexe.t}}
+      "tlsexeold"}
     {"TLS shared" "-shared -melf64ppc tmpdir/tls.o" "" {}
      {{readelf -WSsrl tlsso.r} {objdump -dr tlsso.d}
       {objdump -sj.got tlsso.g} {objdump -sj.tdata tlsso.t}}
@@ -155,6 +161,11 @@ set ppc64elftests {
      {{readelf -WSsrl tlsexetoc.r} {objdump -dr tlsexetoc.d}
       {objdump -sj.got tlsexetoc.g} {objdump -sj.tdata tlsexetoc.t}}
       "tlsexetoc"}
+    {"TLSTOC dynamic old" "-melf64ppc tmpdir/tlstoc.o tmpdir/liboldlib.so"
+     "" {}
+     {{readelf -WSsrl tlsexetoc.r} {objdump -dr tlsexetoc.d}
+      {objdump -sj.got tlsexetoc.g} {objdump -sj.tdata tlsexetoc.t}}
+      "tlsexetocold"}
     {"TLSTOC shared" "-shared -melf64ppc tmpdir/tlstoc.o" "" {}
      {{readelf -WSsrl tlstocso.r} {objdump -dr tlstocso.d}
       {objdump -sj.got tlstocso.g} {objdump -sj.tdata tlstocso.t}}
index 825434e..e7f1e4c 100644 (file)
@@ -8,21 +8,34 @@
 
 Disassembly of section \.text:
 
-.* <_start-0x18>:
+.* <_start-0x4c>:
+.*     e9 63 00 00     ld      r11,0\(r3\)
+.*     e9 83 00 08     ld      r12,8\(r3\)
+.*     7c 60 1b 78     mr      r0,r3
+.*     2c 2b 00 00     cmpdi   r11,0
+.*     7c 6c 6a 14     add     r3,r12,r13
+.*     4d 82 00 20     beqlr   
+.*     7c 03 03 78     mr      r3,r0
+.*     7d 68 02 a6     mflr    r11
+.*     f9 61 00 20     std     r11,32\(r1\)
 .*     f8 41 00 28     std     r2,40\(r1\)
 .*     e9 62 80 48     ld      r11,-32696\(r2\)
 .*     7d 69 03 a6     mtctr   r11
 .*     e9 62 80 58     ld      r11,-32680\(r2\)
 .*     e8 42 80 50     ld      r2,-32688\(r2\)
-.*     4e 80 04 20     bctr
+.*     4e 80 04 21     bctrl
+.*     e9 61 00 20     ld      r11,32\(r1\)
+.*     e8 41 00 28     ld      r2,40\(r1\)
+.*     7d 68 03 a6     mtlr    r11
+.*     4e 80 00 20     blr
 
 .* <_start>:
 .*     e8 62 80 10     ld      r3,-32752\(r2\)
 .*     60 00 00 00     nop
 .*     7c 63 6a 14     add     r3,r3,r13
 .*     38 62 80 18     addi    r3,r2,-32744
-.*     4b ff ff d9     bl      .*
-.*     e8 41 00 28     ld      r2,40\(r1\)
+.*     4b ff ff a5     bl      .*
+.*     60 00 00 00     nop
 .*     3c 6d 00 00     addis   r3,r13,0
 .*     60 00 00 00     nop
 .*     38 63 90 38     addi    r3,r3,-28616
@@ -55,8 +68,9 @@ Disassembly of section \.text:
 .*     e9 4d 90 2a     lwa     r10,-28632\(r13\)
 .*     3d 2d 00 00     addis   r9,r13,0
 .*     a9 49 90 30     lha     r10,-28624\(r9\)
+.*     60 00 00 00     nop
 .*     00 00 00 00 .*
-.*     00 01 01 f0 .*
+.*     00 01 02 00 .*
 .*     7d 88 02 a6     mflr    r12
 .*     42 9f 00 05     bcl-    20,4\*cr7\+so,.*
 .*     7d 68 02 a6     mflr    r11
index 58280df..c68175f 100644 (file)
@@ -7,6 +7,6 @@
 .*: +file format elf64-powerpc
 
 Contents of section \.got:
-.* 00000000 100185c8 ffffffff ffff8018  .*
+.* 00000000 10018618 ffffffff ffff8018  .*
 .* 00000000 00000000 00000000 00000000  .*
 .* 00000000 00000000 00000000 00000000  .*
index b73aaf1..b4be766 100644 (file)
@@ -16,10 +16,10 @@ Section Headers:
  +\[[ 0-9]+\] \.dynstr +.*
  +\[[ 0-9]+\] \.rela\.dyn +.*
  +\[[ 0-9]+\] \.rela\.plt +.*
- +\[[ 0-9]+\] \.text +PROGBITS .* 0+f8 0+ +AX +0 +0 +8
+ +\[[ 0-9]+\] \.text +PROGBITS .* 0+130 0+ +AX +0 +0 +8
  +\[[ 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+150 10 +WA +4 +0 +8
+ +\[[ 0-9]+\] \.dynamic +DYNAMIC .* 0+160 10 +WA +4 +0 +8
  +\[[ 0-9]+\] \.branch_lt + PROGBITS .* 0+ 0+ +WA +0 +0 +8
  +\[[ 0-9]+\] \.got +PROGBITS .* 0+30 08 +WA +0 +0 +8
  +\[[ 0-9]+\] \.plt +.*
@@ -59,16 +59,16 @@ Relocation section '\.rela\.dyn' at offset .* contains 3 entries:
 
 Relocation section '\.rela\.plt' at offset .* contains 1 entries:
  +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
-[0-9a-f ]+R_PPC64_JMP_SLOT +0+ __tls_get_addr \+ 0
+[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
-.* FUNC +GLOBAL DEFAULT +UND __tls_get_addr
 .* TLS +GLOBAL DEFAULT +UND ld
 .* TLS +GLOBAL DEFAULT +9 ld2
 .* NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+.* FUNC +GLOBAL DEFAULT +UND __tls_get_addr_opt
 .* NOTYPE +GLOBAL DEFAULT +ABS _edata
 .* NOTYPE +GLOBAL DEFAULT +ABS _end
 
@@ -96,10 +96,9 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* TLS +LOCAL +DEFAULT +8 le4
 .* TLS +LOCAL +DEFAULT +8 le5
 .* OBJECT +LOCAL +HIDDEN +10 _DYNAMIC
-.* FUNC +LOCAL +DEFAULT +UND \.__tls_get_addr
+.* (FUNC|NOTYPE) +LOCAL +DEFAULT +UND \.__tls_get_addr(|_opt)
 .* GLOBAL DEFAULT +UND gd
 .* GLOBAL DEFAULT +9 le0
-.* GLOBAL DEFAULT +UND __tls_get_addr
 .* GLOBAL DEFAULT +9 ld0
 .* GLOBAL DEFAULT +9 le1
 .* GLOBAL DEFAULT +UND ld
@@ -107,6 +106,7 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* TLS +GLOBAL DEFAULT +9 ld2
 .* TLS +GLOBAL DEFAULT +9 ld1
 .* NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+.* FUNC +GLOBAL +DEFAULT +UND __tls_get_addr_opt
 .* NOTYPE +GLOBAL DEFAULT +ABS _edata
 .* NOTYPE +GLOBAL DEFAULT +ABS _end
 .* TLS +GLOBAL DEFAULT +9 gd0
index c69e335..527ded0 100644 (file)
@@ -12,7 +12,7 @@ Disassembly of section \.text:
 .*:    80 7f ff f0     lwz     r3,-16\(r31\)
 .*:    7c 63 12 14     add     r3,r3,r2
 .*:    38 7f ff f4     addi    r3,r31,-12
-.*:    48 01 01 85     bl      .*<__tls_get_addr@plt>
+.*:    48 01 01 85     bl      .*<__tls_get_addr_opt@plt>
 .*:    3c 62 00 00     addis   r3,r2,0
 .*:    38 63 90 1c     addi    r3,r3,-28644
 .*:    3c 62 00 00     addis   r3,r2,0
@@ -44,4 +44,4 @@ Disassembly of section \.got:
 .*:    4e 80 00 21     blrl
 
 .* <_GLOBAL_OFFSET_TABLE_>:
-.*:    01 81 02 b4 00 00 00 00 00 00 00 00  .*
+.*:    01 81 02 b8 00 00 00 00 00 00 00 00  .*
index 14b7f8c..c2023a8 100644 (file)
@@ -8,4 +8,4 @@
 
 Contents of section \.got:
 .* 00000000 00000000 00000000 4e800021  .*
-.* 018102b4 00000000 00000000           .*
+.* 018102b8 00000000 00000000           .*
index 86a0ab8..f2c1a45 100644 (file)
@@ -57,16 +57,16 @@ Relocation section '\.rela\.dyn' at offset .* contains 2 entries:
 
 Relocation section '\.rela\.plt' at offset .* contains 1 entries:
  Offset +Info +Type +Sym\. Value +Symbol's Name \+ Addend
-[0-9a-f ]+R_PPC_JMP_SLOT[0-9a-f ]+__tls_get_addr \+ 0
+[0-9a-f ]+R_PPC_JMP_SLOT[0-9a-f ]+__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
-.* FUNC +GLOBAL DEFAULT +UND __tls_get_addr
 .* TLS +GLOBAL DEFAULT +UND ld
 .* NOTYPE +GLOBAL DEFAULT +ABS __end
 .* NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+.* FUNC +GLOBAL DEFAULT +UND __tls_get_addr_opt
 .* NOTYPE +GLOBAL DEFAULT +ABS _edata
 .* NOTYPE +GLOBAL DEFAULT +ABS _end
 
@@ -96,7 +96,6 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* OBJECT +LOCAL +HIDDEN +11 _GLOBAL_OFFSET_TABLE_
 .* TLS +GLOBAL DEFAULT +UND gd
 .* TLS +GLOBAL DEFAULT +9 le0
-.* FUNC +GLOBAL DEFAULT +UND __tls_get_addr
 .* TLS +GLOBAL DEFAULT +9 ld0
 .* TLS +GLOBAL DEFAULT +9 le1
 .* TLS +GLOBAL DEFAULT +UND ld
@@ -105,6 +104,7 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* TLS +GLOBAL DEFAULT +9 ld2
 .* TLS +GLOBAL DEFAULT +9 ld1
 .* NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+.* FUNC +GLOBAL DEFAULT +UND __tls_get_addr_opt
 .* NOTYPE +GLOBAL DEFAULT +ABS _edata
 .* NOTYPE +GLOBAL DEFAULT +ABS _end
 .* TLS +GLOBAL DEFAULT +9 gd0
index d6a0388..83b1aca 100644 (file)
@@ -8,21 +8,34 @@
 
 Disassembly of section \.text:
 
-.* <_start-0x18>:
+.* <_start-0x4c>:
+.*     e9 63 00 00     ld      r11,0\(r3\)
+.*     e9 83 00 08     ld      r12,8\(r3\)
+.*     7c 60 1b 78     mr      r0,r3
+.*     2c 2b 00 00     cmpdi   r11,0
+.*     7c 6c 6a 14     add     r3,r12,r13
+.*     4d 82 00 20     beqlr   
+.*     7c 03 03 78     mr      r3,r0
+.*     7d 68 02 a6     mflr    r11
+.*     f9 61 00 20     std     r11,32\(r1\)
 .*     f8 41 00 28     std     r2,40\(r1\)
 .*     e9 62 80 70     ld      r11,-32656\(r2\)
 .*     7d 69 03 a6     mtctr   r11
 .*     e9 62 80 80     ld      r11,-32640\(r2\)
 .*     e8 42 80 78     ld      r2,-32648\(r2\)
-.*     4e 80 04 20     bctr
+.*     4e 80 04 21     bctrl
+.*     e9 61 00 20     ld      r11,32\(r1\)
+.*     e8 41 00 28     ld      r2,40\(r1\)
+.*     7d 68 03 a6     mtlr    r11
+.*     4e 80 00 20     blr
 
 .* <_start>:
 .*     38 62 80 08     addi    r3,r2,-32760
-.*     4b ff ff e5     bl      .*
-.*     e8 41 00 28     ld      r2,40\(r1\)
+.*     4b ff ff b1     bl      .*
+.*     60 00 00 00     nop
 .*     38 62 80 18     addi    r3,r2,-32744
-.*     4b ff ff d9     bl      .*
-.*     e8 41 00 28     ld      r2,40\(r1\)
+.*     4b ff ff a5     bl      .*
+.*     60 00 00 00     nop
 .*     3c 6d 00 00     addis   r3,r13,0
 .*     60 00 00 00     nop
 .*     38 63 90 38     addi    r3,r3,-28616
@@ -39,8 +52,9 @@ Disassembly of section \.text:
 .*     89 4d 90 60     lbz     r10,-28576\(r13\)
 .*     3d 2d 00 00     addis   r9,r13,0
 .*     99 49 90 68     stb     r10,-28568\(r9\)
+.*     60 00 00 00     nop
 .*     00 00 00 00 .*
-.*     00 01 02 18 .*
+.*     00 01 02 28 .*
 .*     7d 88 02 a6     mflr    r12
 .*     42 9f 00 05     bcl-    20,4\*cr7\+so,.*
 .*     7d 68 02 a6     mflr    r11
index df3994c..387e9cd 100644 (file)
@@ -7,7 +7,7 @@
 .*: +file format elf64-powerpc
 
 Contents of section \.got:
-.* 00000000 10018568 00000000 00000000  .*
+.* 00000000 100185b0 00000000 00000000  .*
 .* 00000000 00000000 00000000 00000000  .*
 .* 00000000 00000000 00000000 00000001  .*
 .* 00000000 00000000 00000000 00000001  .*
index e16bbf4..d1f75df 100644 (file)
@@ -16,10 +16,10 @@ Section Headers:
  +\[[ 0-9]+\] \.dynstr +.*
  +\[[ 0-9]+\] \.rela\.dyn +.*
  +\[[ 0-9]+\] \.rela\.plt +.*
- +\[[ 0-9]+\] \.text +PROGBITS .* 0+b8 0+ +AX +0 +0 +8
+ +\[[ 0-9]+\] \.text +PROGBITS .* 0+f0 0+ +AX +0 +0 +8
  +\[[ 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+150 10 +WA +4 +0 +8
+ +\[[ 0-9]+\] \.dynamic +DYNAMIC .* 0+160 10 +WA +4 +0 +8
  +\[[ 0-9]+\] \.branch_lt +PROGBITS .* 0+ 0+ +WA +0 +0 +8
  +\[[ 0-9]+\] \.got +PROGBITS .* 0+58 08 +WA +0 +0 +8
  +\[[ 0-9]+\] \.plt +.*
@@ -59,15 +59,15 @@ Relocation section '\.rela\.dyn' at offset .* contains 3 entries:
 
 Relocation section '\.rela\.plt' at offset .* contains 1 entries:
  +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
-[0-9a-f ]+R_PPC64_JMP_SLOT +0+ __tls_get_addr \+ 0
+[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
-.* FUNC +GLOBAL DEFAULT +UND __tls_get_addr
 .* TLS +GLOBAL DEFAULT +UND ld
 .* NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+.* FUNC +GLOBAL DEFAULT +UND __tls_get_addr_opt
 .* NOTYPE +GLOBAL DEFAULT +ABS _edata
 .* NOTYPE +GLOBAL DEFAULT +ABS _end
 
@@ -96,10 +96,9 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* TLS +LOCAL +DEFAULT +8 le5
 .* NOTYPE +LOCAL +DEFAULT +12 \.Lie0
 .* OBJECT +LOCAL +HIDDEN +10 _DYNAMIC
-.* FUNC +LOCAL +DEFAULT +UND \.__tls_get_addr
+.* (FUNC|NOTYPE) +LOCAL +DEFAULT +UND \.__tls_get_addr(|_opt)
 .* TLS +GLOBAL DEFAULT +UND gd
 .* TLS +GLOBAL DEFAULT +9 le0
-.* FUNC +GLOBAL DEFAULT +UND __tls_get_addr
 .* TLS +GLOBAL DEFAULT +9 ld0
 .* TLS +GLOBAL DEFAULT +9 le1
 .* TLS +GLOBAL DEFAULT +UND ld
@@ -107,6 +106,7 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* TLS +GLOBAL DEFAULT +9 ld2
 .* TLS +GLOBAL DEFAULT +9 ld1
 .* NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+.* FUNC +GLOBAL DEFAULT +UND __tls_get_addr_opt
 .* NOTYPE +GLOBAL DEFAULT +ABS _edata
 .* NOTYPE +GLOBAL DEFAULT +ABS _end
 .* TLS +GLOBAL DEFAULT +9 gd0
index 08f27a2..59c40d2 100644 (file)
@@ -1,10 +1,12 @@
-       .global .__tls_get_addr,__tls_get_addr,gd,ld
-       .type .__tls_get_addr,@function
+       .global __tls_get_addr,__tls_get_addr_opt,gd,ld
+       .type __tls_get_addr,@function
+       .type __tls_get_addr_opt,@function
 
        .section ".opd","aw",@progbits
 __tls_get_addr:
+__tls_get_addr_opt:
        .align 3
-       .quad   .__tls_get_addr
+       .quad   .L.__tls_get_addr
        .quad   .TOC.@tocbase
        .quad   0
 
@@ -17,5 +19,6 @@ gd:   .space 8
 ld:    .long 0xc0ffee
 
        .text
-.__tls_get_addr:
+.L.__tls_get_addr:
        blr
+       .size __tls_get_addr,. - .L.__tls_get_addr
index 98cd3e9..14dc966 100644 (file)
@@ -1,5 +1,6 @@
-       .global __tls_get_addr,gd,ld
+       .global __tls_get_addr,__tls_get_addr_opt,gd,ld
        .type __tls_get_addr,@function
+       .type __tls_get_addr_opt,@function
 
        .section ".tbss","awT",@nobits
        .align 2
@@ -11,4 +12,5 @@ ld:   .long 0xc0ffee
 
        .text
 __tls_get_addr:
+__tls_get_addr_opt:
        blr