Add PowerPC64 ld --tls-get-addr-optimize.
authorAlan Modra <amodra@gmail.com>
Fri, 18 Sep 2015 06:47:49 +0000 (16:17 +0930)
committerAlan Modra <amodra@gmail.com>
Fri, 18 Sep 2015 07:08:03 +0000 (16:38 +0930)
Sometimes it may be of benefit to force use of the __tls_get_addr_opt
call stub even when the glibc being used during linking does not
advertise __tls_get_addr_opt.

bfd/
* elf64-ppc.h (struct ppc64_elf_params <tls_get_addr_opt>): Rename
from no_tls_get_addr_opt.
* elf64-ppc.c: Update for rename and inversion of tls_get_addr_opt.
(ppc64_elf_tls_setup): Set tls_get_addr_opt to 0 only when at
default of -1.
ld/
* emultempl/ppc64elf.em (params): Init tls_get_addr_opt field to -1.
(OPTION_TLS_GET_ADDR_OPT): Define.
(PARSE_AND_LIST_LONGOPTS): Handle --tls-get-addr-opt.
(PARSE_AND_LIST_OPTIONS, PARSE_AND_LIST_ARGS_CASES): Likewise.
* ld.texinfo: Document --tls-get-addr-optimize and
--no-tls-get-addr-optimize.

bfd/ChangeLog
bfd/elf64-ppc.c
bfd/elf64-ppc.h
ld/ChangeLog
ld/emultempl/ppc64elf.em
ld/ld.texinfo

index 26a05378dcebb9145cdb0f20e34d3884671bd05a..3e0c7b8bb11fc89607cde7595fc17f6d69d6dc54 100644 (file)
@@ -1,3 +1,11 @@
+2015-09-18  Alan Modra  <amodra@gmail.com>
+
+       * elf64-ppc.h (struct ppc64_elf_params <tls_get_addr_opt>): Rename
+       from no_tls_get_addr_opt.
+       * elf64-ppc.c: Update for rename and inversion of tls_get_addr_opt.
+       (ppc64_elf_tls_setup): Set tls_get_addr_opt to 0 only when at
+       default of -1.
+
 2015-09-17  Alan Modra  <amodra@gmail.com>
 
        PR 18867
index f179f6d2df8f80e6deba98e09d9025e60bf14dc0..5ad5f48c0e2c90df678335b6f176db9c8cadd0de 100644 (file)
@@ -8136,7 +8136,7 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
   htab->tls_get_addr_fd = ((struct ppc_link_hash_entry *)
                           elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
                                                 FALSE, FALSE, TRUE));
-  if (!htab->params->no_tls_get_addr_opt)
+  if (htab->params->tls_get_addr_opt)
     {
       struct elf_link_hash_entry *opt, *opt_fd, *tga, *tga_fd;
 
@@ -8203,8 +8203,8 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
                }
            }
        }
-      else
-       htab->params->no_tls_get_addr_opt = TRUE;
+      else if (htab->params->tls_get_addr_opt < 0)
+       htab->params->tls_get_addr_opt = 0;
     }
   return _bfd_elf_tls_setup (info->output_bfd, info);
 }
@@ -10125,7 +10125,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
            return FALSE;
        }
 
-      tls_opt = (!htab->params->no_tls_get_addr_opt
+      tls_opt = (htab->params->tls_get_addr_opt
                 && htab->tls_get_addr_fd != NULL
                 && htab->tls_get_addr_fd->elf.plt.plist != NULL);
       if (tls_opt || !htab->opd_abi)
@@ -10310,7 +10310,7 @@ plt_stub_size (struct ppc_link_hash_table *htab,
   if (stub_entry->h != NULL
       && (stub_entry->h == htab->tls_get_addr_fd
          || stub_entry->h == htab->tls_get_addr)
-      && !htab->params->no_tls_get_addr_opt)
+      && htab->params->tls_get_addr_opt)
     size += 13 * 4;
   return size;
 }
@@ -10354,7 +10354,7 @@ build_plt_stub (struct ppc_link_hash_table *htab,
       && plt_thread_safe
       && !((stub_entry->h == htab->tls_get_addr_fd
            || stub_entry->h == htab->tls_get_addr)
-          && !htab->params->no_tls_get_addr_opt))
+          && htab->params->tls_get_addr_opt))
     {
       bfd_vma pltoff = stub_entry->plt_ent->plt.offset & ~1;
       bfd_vma pltindex = ((pltoff - PLT_INITIAL_ENTRY_SIZE (htab))
@@ -11005,7 +11005,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (stub_entry->h != NULL
          && (stub_entry->h == htab->tls_get_addr_fd
              || stub_entry->h == htab->tls_get_addr)
-         && !htab->params->no_tls_get_addr_opt)
+         && htab->params->tls_get_addr_opt)
        p = build_tls_get_addr_stub (htab, stub_entry, loc, off, r);
       else
        p = build_plt_stub (htab, stub_entry, loc, off, r);
@@ -13911,7 +13911,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                          if (h != NULL
                              && (h == htab->tls_get_addr_fd
                                  || h == htab->tls_get_addr)
-                             && !htab->params->no_tls_get_addr_opt)
+                             && htab->params->tls_get_addr_opt)
                            {
                              /* Special stub used, leave nop alone.  */
                            }
index 19f72b5fbf14d1ff2956c0d5246719bb4397fe9d..d035ffcce93cdee001d8548eecfc1decd0ce94cd 100644 (file)
@@ -34,7 +34,7 @@ struct ppc64_elf_params
   bfd_signed_vma group_size;
 
   /* Whether to use a special call stub for __tls_get_addr.  */
-  int no_tls_get_addr_opt;
+  int tls_get_addr_opt;
 
   /* Whether to allow multiple toc sections.  */
   int no_multi_toc;
index 96359f5a7c3fe127dfe5ad8c9e405f77e9a611a6..f495ed2a3226720af008e9213327c0c5ef1d0a80 100644 (file)
@@ -1,3 +1,12 @@
+2015-09-18  Alan Modra  <amodra@gmail.com>
+
+       * emultempl/ppc64elf.em (params): Init tls_get_addr_opt field to -1.
+       (OPTION_TLS_GET_ADDR_OPT): Define.
+       (PARSE_AND_LIST_LONGOPTS): Handle --tls-get-addr-opt.
+       (PARSE_AND_LIST_OPTIONS, PARSE_AND_LIST_ARGS_CASES): Likewise.
+       * ld.texinfo: Document --tls-get-addr-optimize and
+       --no-tls-get-addr-optimize.
+
 2015-09-18  Alan Modra  <amodra@gmail.com>
 
        PR ld/18963
index 41942f900ed343a5c8e16f60dbabf3a4da45436d..08bd5d422dfd29a3e674fdbfb32b3da6f0f81b5a 100644 (file)
@@ -37,7 +37,7 @@ static void ppc_layout_sections_again (void);
 static struct ppc64_elf_params params = { NULL,
                                          &ppc_add_stub_section,
                                          &ppc_layout_sections_again,
-                                         1, 0, 0,
+                                         1, -1, 0,
                                          ${DEFAULT_PLT_STATIC_CHAIN-0}, -1, 0,
                                          0, -1, -1, 0};
 
@@ -699,7 +699,8 @@ PARSE_AND_LIST_PROLOGUE=${PARSE_AND_LIST_PROLOGUE}'
 #define OPTION_DOTSYMS                 (OPTION_NO_SAVRES + 1)
 #define OPTION_NO_DOTSYMS              (OPTION_DOTSYMS + 1)
 #define OPTION_NO_TLS_OPT              (OPTION_NO_DOTSYMS + 1)
-#define OPTION_NO_TLS_GET_ADDR_OPT     (OPTION_NO_TLS_OPT + 1)
+#define OPTION_TLS_GET_ADDR_OPT                (OPTION_NO_TLS_OPT + 1)
+#define OPTION_NO_TLS_GET_ADDR_OPT     (OPTION_TLS_GET_ADDR_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)
@@ -722,6 +723,7 @@ PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}'
   { "save-restore-funcs", no_argument, NULL, OPTION_SAVRES },
   { "no-save-restore-funcs", no_argument, NULL, OPTION_NO_SAVRES },
   { "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 },
   { "no-opd-optimize", no_argument, NULL, OPTION_NO_OPD_OPT },
   { "no-toc-optimize", no_argument, NULL, OPTION_NO_TOC_OPT },
@@ -786,6 +788,9 @@ PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'
   --no-tls-optimize           Don'\''t try to optimize TLS accesses.\n"
                   ));
   fprintf (file, _("\
+  --tls-get-addr-optimize     Force use of special __tls_get_addr call.\n"
+                  ));
+  fprintf (file, _("\
   --no-tls-get-addr-optimize  Don'\''t use a special __tls_get_addr call.\n"
                   ));
   fprintf (file, _("\
@@ -877,8 +882,12 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
       no_tls_opt = 1;
       break;
 
+    case OPTION_TLS_GET_ADDR_OPT:
+      params.tls_get_addr_opt = 1;
+      break;
+
     case OPTION_NO_TLS_GET_ADDR_OPT:
-      params.no_tls_get_addr_opt = 1;
+      params.tls_get_addr_opt = 0;
       break;
 
     case OPTION_NO_OPD_OPT:
@@ -903,7 +912,7 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
 
     case OPTION_TRADITIONAL_FORMAT:
       no_tls_opt = 1;
-      params.no_tls_get_addr_opt = 1;
+      params.tls_get_addr_opt = 0;
       no_opd_opt = 1;
       no_toc_opt = 1;
       params.no_multi_toc = 1;
index be1d4906fae107ea3b33c50544c09e9e1fd3d469..57f1730e5abd1e825d2af6b85b0009adc1ebfe66 100644 (file)
@@ -7133,6 +7133,21 @@ PowerPC64 @command{ld} normally performs some optimization of code
 sequences used to access Thread-Local Storage.  Use this option to
 disable the optimization.
 
+@cindex PowerPC64 __tls_get_addr optimization
+@kindex --tls-get-addr-optimize
+@kindex --no-tls-get-addr-optimize
+@item --tls-get-addr-optimize, --no-tls-get-addr-optimize
+These options control whether 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.
+
 @cindex PowerPC64 OPD optimization
 @kindex --no-opd-optimize
 @item --no-opd-optimize