]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Power10 stub selection
authorAlan Modra <amodra@gmail.com>
Fri, 17 Jul 2020 07:17:28 +0000 (16:47 +0930)
committerAlan Modra <amodra@gmail.com>
Sun, 19 Jul 2020 03:01:15 +0000 (12:31 +0930)
This patch better supports mixing of power10 and non-power10 code,
as might be seen in a cpu-optimized library using ifuncs to select
functions optimized for a given cpu.  Using -Wl,--no-power10-stubs
isn't that good in this situation since non-power10 notoc stubs are
slower and larger than the power10 variants, which you'd like to use
on power10 code paths.

With this change, power10 pc-relative code that makes calls marked
@notoc uses power10 stubs if stubs are necessary, and other calls use
non-power10 instructions in stubs.  This will mean that if gcc is
generating code for -mcpu=power10 but with pc-rel disabled then you'll
get the older stubs even on power10 (unless you force with
-Wl,--power10-stubs).  That shouldn't be too big a problem: stubs that
use r2 are reasonable.  It's just the ones that set up addressing
using "mflr 12; bcl 20,31,.+4; mflr 11; mtlr 12" that should be
avoided if possible.

bfd/
* elf64-ppc.c (struct ppc_link_hash_table): Add has_power10_relocs.
(select_alt_stub): New function.
(ppc_get_stub_entry): Use it here.
(ppc64_elf_check_relocs): Set had_power10_relocs rather than
power10_stubs.
(ppc64_elf_size_stubs): Clear power10_stubs here instead.  Don't
merge notoc stubs with other varieties when power10_stubs is "auto".
Instead dup the stub hash table entry.
(plt_stub_size, ppc_build_one_stub, ppc_size_one_stub): Adjust
tests of power10_stubs.
ld/
* emultempl/ppc64elf.em (power10-stubs): Accept optional "auto" arg.
* ld.texi (power10-stubs): Update.
* testsuite/ld-powerpc/callstub-1.d: Force --power10-stubs.
* testsuite/ld-powerpc/callstub-2.d: Relax branch offset comparison.
* testsuite/ld-powerpc/callstub-4.d: New test.
* testsuite/ld-powerpc/notoc.d: Force --no-power10-stubs.
* testsuite/ld-powerpc/notoc3.d,
* testsuite/ld-powerpc/notoc3.s,
* testsuite/ld-powerpc/notoc3.wf: New test.
* testsuite/ld-powerpc/powerpc.exp: Run new tests.  Pass
--no-power10-stubs for notoc link.

(cherry picked from commit e10a07b32dc1faed25b5bbcbbc47d68e2ff537b9)

13 files changed:
bfd/ChangeLog
bfd/elf64-ppc.c
ld/ChangeLog
ld/emultempl/ppc64elf.em
ld/ld.texi
ld/testsuite/ld-powerpc/callstub-1.d
ld/testsuite/ld-powerpc/callstub-2.d
ld/testsuite/ld-powerpc/callstub-4.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/notoc.d
ld/testsuite/ld-powerpc/notoc3.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/notoc3.s [new file with mode: 0644]
ld/testsuite/ld-powerpc/notoc3.wf [new file with mode: 0644]
ld/testsuite/ld-powerpc/powerpc.exp

index 1a25c8e99c86792774bd262c101328e7ec647840..631493e235d9fbe5a4f9b99c6605384e6e93a8e1 100644 (file)
@@ -1,3 +1,16 @@
+2020-07-19  Alan Modra  <amodra@gmail.com>
+
+       * elf64-ppc.c (struct ppc_link_hash_table): Add has_power10_relocs.
+       (select_alt_stub): New function.
+       (ppc_get_stub_entry): Use it here.
+       (ppc64_elf_check_relocs): Set had_power10_relocs rather than
+       power10_stubs.
+       (ppc64_elf_size_stubs): Clear power10_stubs here instead.  Don't
+       merge notoc stubs with other varieties when power10_stubs is "auto".
+       Instead dup the stub hash table entry.
+       (plt_stub_size, ppc_build_one_stub, ppc_size_one_stub): Adjust
+       tests of power10_stubs.
+
 2020-07-15  Hans-Peter Nilsson  <hp@bitrange.com>
 
        * elf64-mmix.c (mmix_elf_relax_section): Improve accounting for
index e54f561019410a0454a5cd21eb48b107ca92630b..8d622fb90921e41d889c830d7368d714e94ff839 100644 (file)
@@ -3245,6 +3245,9 @@ struct ppc_link_hash_table
   /* Whether calls are made via the PLT from NOTOC functions.  */
   unsigned int notoc_plt:1;
 
+  /* Whether any code linked seems to be Power10.  */
+  unsigned int has_power10_relocs:1;
+
   /* Incremented every time we size stubs.  */
   unsigned int stub_iteration;
 
@@ -3679,6 +3682,37 @@ ppc_stub_name (const asection *input_section,
   return stub_name;
 }
 
+/* If mixing power10 with non-power10 code and --power10-stubs is not
+   specified (or is auto) then calls using @notoc relocations that
+   need a stub will utilize power10 instructions in the stub, and
+   calls without @notoc relocations will not use power10 instructions.
+   The two classes of stubs are stored in separate stub_hash_table
+   entries having the same key string.  The two entries will always be
+   adjacent on entry->root.next chain, even if hash table resizing
+   occurs.  This function selects the correct entry to use.  */
+
+static struct ppc_stub_hash_entry *
+select_alt_stub (struct ppc_stub_hash_entry *entry, bfd_boolean notoc)
+{
+  bfd_boolean have_notoc;
+
+  have_notoc = (entry->stub_type == ppc_stub_plt_call_notoc
+               || entry->stub_type == ppc_stub_plt_branch_notoc
+               || entry->stub_type == ppc_stub_long_branch_notoc);
+
+  if (have_notoc != notoc)
+    {
+      const char *stub_name = entry->root.string;
+
+      entry = (struct ppc_stub_hash_entry *) entry->root.next;
+      if (entry != NULL
+         && entry->root.string != stub_name)
+       entry = NULL;
+    }
+
+  return entry;
+}
+
 /* Look up an entry in the stub hash.  Stub entries are cached because
    creating the stub name takes a bit of time.  */
 
@@ -3723,6 +3757,13 @@ ppc_get_stub_entry (const asection *input_section,
       free (stub_name);
     }
 
+  if (stub_entry != NULL && htab->params->power10_stubs == -1)
+    {
+      bfd_boolean notoc = ELF64_R_TYPE (rel->r_info) == R_PPC64_REL24_NOTOC;
+
+      stub_entry = select_alt_stub (stub_entry, notoc);
+    }
+
   return stub_entry;
 }
 
@@ -4599,8 +4640,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_PLT_PCREL34:
        case R_PPC64_PLT_PCREL34_NOTOC:
        case R_PPC64_PCREL28:
-         if (htab->params->power10_stubs < 0)
-           htab->params->power10_stubs = 1;
+         htab->has_power10_relocs = 1;
          break;
        default:
          break;
@@ -10761,7 +10801,7 @@ plt_stub_size (struct ppc_link_hash_table *htab,
 
   if (stub_entry->stub_type >= ppc_stub_plt_call_notoc)
     {
-      if (htab->params->power10_stubs > 0)
+      if (htab->params->power10_stubs != 0)
        {
          bfd_vma start = (stub_entry->stub_offset
                           + stub_entry->group->stub_sec->output_offset
@@ -11602,7 +11642,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       relp = p;
       num_rel = 0;
-      if (htab->params->power10_stubs > 0)
+      if (htab->params->power10_stubs != 0)
        {
          bfd_boolean load = stub_entry->stub_type >= ppc_stub_plt_call_notoc;
          p = build_power10_offset (htab->params->stub_bfd, p, off, odd, load);
@@ -11641,7 +11681,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (info->emitrelocations)
        {
          bfd_vma roff = relp - stub_entry->group->stub_sec->contents;
-         if (htab->params->power10_stubs > 0)
+         if (htab->params->power10_stubs != 0)
            num_rel += num_relocs_for_power10_offset (off, odd);
          else
            {
@@ -11651,7 +11691,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
          r = get_relocs (stub_entry->group->stub_sec, num_rel);
          if (r == NULL)
            return FALSE;
-         if (htab->params->power10_stubs > 0)
+         if (htab->params->power10_stubs != 0)
            r = emit_relocs_for_power10_offset (info, r, roff, targ, off, odd);
          else
            r = emit_relocs_for_offset (info, r, roff, targ, off);
@@ -11669,7 +11709,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
            }
        }
 
-      if (htab->params->power10_stubs <= 0
+      if (htab->params->power10_stubs == 0
          && htab->glink_eh_frame != NULL
          && htab->glink_eh_frame->size != 0)
        {
@@ -12017,7 +12057,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (info->emitrelocations)
        {
          unsigned int num_rel;
-         if (htab->params->power10_stubs > 0)
+         if (htab->params->power10_stubs != 0)
            num_rel = num_relocs_for_power10_offset (off, odd);
          else
            num_rel = num_relocs_for_offset (off - 8);
@@ -12025,7 +12065,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
          stub_entry->group->stub_sec->flags |= SEC_RELOC;
        }
 
-      if (htab->params->power10_stubs > 0)
+      if (htab->params->power10_stubs != 0)
        extra = size_power10_offset (off, odd);
       else
        extra = size_offset (off - 8);
@@ -12036,7 +12076,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
         calculated.  */
       off -= extra;
 
-      if (htab->params->power10_stubs <= 0)
+      if (htab->params->power10_stubs == 0)
        {
          /* After the bcl, lr has been modified so we need to emit
             .eh_frame info saying the return address is in r12.  */
@@ -12099,7 +12139,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (info->emitrelocations)
        {
          unsigned int num_rel;
-         if (htab->params->power10_stubs > 0)
+         if (htab->params->power10_stubs != 0)
            num_rel = num_relocs_for_power10_offset (off, odd);
          else
            num_rel = num_relocs_for_offset (off - 8);
@@ -12109,7 +12149,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       size = plt_stub_size (htab, stub_entry, off);
 
-      if (htab->params->power10_stubs <= 0)
+      if (htab->params->power10_stubs == 0)
        {
          /* After the bcl, lr has been modified so we need to emit
             .eh_frame info saying the return address is in r12.  */
@@ -13034,6 +13074,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
   if (htab == NULL)
     return FALSE;
 
+  if (htab->params->power10_stubs == -1 && !htab->has_power10_relocs)
+    htab->params->power10_stubs = 0;
+
   if (htab->params->plt_thread_safe == -1 && !bfd_link_executable (info))
     htab->params->plt_thread_safe = 1;
   if (!htab->opd_abi)
@@ -13409,6 +13452,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
                  if (stub_entry != NULL)
                    {
                      enum ppc_stub_type old_type;
+
                      /* A stub has already been created, but it may
                         not be the required type.  We shouldn't be
                         transitioning from plt_call to long_branch
@@ -13416,6 +13460,39 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
                         upgrading from plt_call to plt_call_r2save or
                         from long_branch to long_branch_r2off.  */
                      free (stub_name);
+                     if (htab->params->power10_stubs == -1)
+                       {
+                         /* For --power10-stubs=auto, don't merge _notoc
+                            and other varieties of stubs.  (The _both
+                            variety won't be created.)  */
+                         bfd_boolean notoc = r_type == R_PPC64_REL24_NOTOC;
+                         struct ppc_stub_hash_entry *alt_stub
+                           = select_alt_stub (stub_entry, notoc);
+
+                         if (alt_stub == NULL)
+                           {
+                             alt_stub = (struct ppc_stub_hash_entry *)
+                               stub_hash_newfunc (NULL,
+                                                  &htab->stub_hash_table,
+                                                  stub_entry->root.string);
+                             if (alt_stub == NULL)
+                               {
+                                 /* xgettext:c-format */
+                                 _bfd_error_handler
+                                   (_("%pB: cannot create stub entry %s"),
+                                    section->owner, stub_entry->root.string);
+                                 goto error_ret_free_internal;
+                               }
+                             *alt_stub = *stub_entry;
+                             stub_entry->root.next = &alt_stub->root;
+                             if (notoc)
+                               /* Sort notoc stubs first, for no good
+                                  reason.  */
+                               alt_stub = stub_entry;
+                             alt_stub->stub_type = stub_type;
+                           }
+                         stub_entry = alt_stub;
+                       }
                      old_type = stub_entry->stub_type;
                      switch (old_type)
                        {
index 2985f105306a752e5e66c6a889a331b2e75ccc69..ca61ce291d628fdf0a50b6ed1cee14a5c8c97d9a 100644 (file)
@@ -1,3 +1,17 @@
+2020-07-19  Alan Modra  <amodra@gmail.com>
+
+       * emultempl/ppc64elf.em (power10-stubs): Accept optional "auto" arg.
+       * ld.texi (power10-stubs): Update.
+       * testsuite/ld-powerpc/callstub-1.d: Force --power10-stubs.
+       * testsuite/ld-powerpc/callstub-2.d: Relax branch offset comparison.
+       * testsuite/ld-powerpc/callstub-4.d: New test.
+       * testsuite/ld-powerpc/notoc.d: Force --no-power10-stubs.
+       * testsuite/ld-powerpc/notoc3.d,
+       * testsuite/ld-powerpc/notoc3.s,
+       * testsuite/ld-powerpc/notoc3.wf: New test.
+       * testsuite/ld-powerpc/powerpc.exp: Run new tests.  Pass
+       --no-power10-stubs for notoc link.
+
 2020-07-15  Hans-Peter Nilsson  <hp@bitrange.com>
 
        * testsuite/ld-mmix/undef-1.d, testsuite/ld-mmix/undef-1m.d,
index 4987243fa1e361a2b50b67f2c68bb60a03cb5b00..1331d03113bd7c3091558f423eac86bb16008653 100644 (file)
@@ -716,7 +716,7 @@ PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}'
   { "no-plt-align", no_argument, NULL, OPTION_NO_PLT_ALIGN },
   { "plt-localentry", optional_argument, NULL, OPTION_PLT_LOCALENTRY },
   { "no-plt-localentry", no_argument, NULL, OPTION_NO_PLT_LOCALENTRY },
-  { "power10-stubs", no_argument, NULL, OPTION_POWER10_STUBS },
+  { "power10-stubs", optional_argument, NULL, OPTION_POWER10_STUBS },
   { "no-power10-stubs", no_argument, NULL, OPTION_NO_POWER10_STUBS },
   { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS },
   { "no-emit-stub-syms", no_argument, NULL, OPTION_NO_STUBSYMS },
@@ -773,7 +773,7 @@ PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'
   --no-plt-localentry         Don'\''t optimize ELFv2 calls\n"
                   ));
   fprintf (file, _("\
-  --power10-stubs             Use Power10 PLT call stubs (default auto)\n"
+  --power10-stubs [=auto]     Use Power10 PLT call stubs (default auto)\n"
                   ));
   fprintf (file, _("\
   --no-power10-stubs          Don'\''t use Power10 PLT call stubs\n"
@@ -889,7 +889,20 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
       break;
 
     case OPTION_POWER10_STUBS:
-      params.power10_stubs = 1;
+      if (optarg != NULL)
+       {
+         if (strcasecmp (optarg, "auto") == 0)
+           params.power10_stubs = -1;
+         else if (strcasecmp (optarg, "yes") == 0)
+           params.power10_stubs = 1;
+         else if (strcasecmp (optarg, "no") == 0)
+           params.power10_stubs = 0;
+         else
+           einfo (_("%F%P: invalid --power10-stubs argument `%s'\''\n"),
+                  optarg);
+       }
+      else
+       params.power10_stubs = 1;
       break;
 
     case OPTION_NO_POWER10_STUBS:
index 165a3d935e16e9c7497bdf51c1f50ae39bdc2e76..2a93e9456aca3c2bed36f539ba223c9955ea4cdd 100644 (file)
@@ -7922,15 +7922,13 @@ care.  @option{--no-plt-localentry} is the default.
 @itemx --no-power10-stubs
 When PowerPC64 @command{ld} links input object files containing
 relocations used on power10 prefixed instructions it normally creates
-linkage stubs (PLT call and long branch) using power10 instructions.
-In particular for @code{@@notoc} PLT calls where @code{r2} is not
-known the power10 stubs are smaller and faster, so are preferred for
+linkage stubs (PLT call and long branch) using power10 instructions
+for @code{@@notoc} PLT calls where @code{r2} is not known.  The
+power10 notoc stubs are smaller and faster, so are preferred for
 power10.  @option{--power10-stubs} and @option{--no-power10-stubs}
 allow you to override the linker's selection of stub instructions.
-For example, when linking a shared library that contains cpu-optimized
-versions of functions for both power9 and power10, you might use
-@option{--no-power10-stubs} so that power9 code making calls doesn't
-attempt to execute power10 instructions.
+@option{--power10-stubs=auto} allows the user to select the default
+auto mode.
 @end table
 
 @ifclear GENERIC
index 21eea767844b6ac71f3bb5842cc26ef84eb160f2..48efdfba0fa702033cf41d5b8814da472a2a9051 100644 (file)
@@ -1,5 +1,5 @@
 #as: -a64 -mpower10
-#ld: -melf64ppc -shared --plt-align=0 --hash-style=gnu
+#ld: -melf64ppc -shared --plt-align=0 --power10-stubs --hash-style=gnu
 #objdump: -dr -Mpower10
 
 .*
@@ -20,10 +20,10 @@ Disassembly of section \.text:
 .*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
 .*:    (4e 80 04 20|20 04 80 4e)       bctr
 #...
-.*:    (4b ff ff c1|c1 ff ff 4b)       bl      .*\.plt_call\.f1>
+
+.*<_start>:
+.*:    (4b ff .. ..|.. .. ff 4b)       bl      .*\.plt_call\.f1>
 .*:    (e8 41 00 18|18 00 41 e8)       ld      r2,24\(r1\)
-.*:    (4b ff ff bd|bd ff ff 4b)       bl      .*\.plt_call\.f1\+0x4>
-.*:    (4b ff ff cd|cd ff ff 4b)       bl      .*\.plt_call\.f2>
-.*:    (04 10 00 01|01 00 10 04)       pld     r3,.*
-.*:    (e4 60 .. ..|.. .. 60 e4) 
+.*:    (4b ff .. ..|.. .. ff 4b)       bl      .*\.plt_call\.f1\+0x4>
+.*:    (4b ff .. ..|.. .. ff 4b)       bl      .*\.plt_call\.f2>
 #pass
index 603670710a51ac3b5714406b990075e89f947fdc..5b43783aae15bba150ff004cd7c0522dba901654 100644 (file)
@@ -27,9 +27,9 @@ Disassembly of section \.text:
 .*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
 .*:    (4e 80 04 20|20 04 80 4e)       bctr
 
-#...
-.*:    (4b ff ff bd|bd ff ff 4b)       bl      .*\.plt_call\.f1>
+.*<_start>:
+.*:    (4b ff .. ..|.. .. ff 4b)       bl      .*\.plt_call\.f1>
 .*:    (e8 41 00 18|18 00 41 e8)       ld      r2,24\(r1\)
-.*:    (4b ff ff b9|b9 ff ff 4b)       bl      .*\.plt_call\.f1\+0x4>
-.*:    (4b ff ff d5|d5 ff ff 4b)       bl      .*\.plt_call\.f2>
+.*:    (4b ff .. ..|.. .. ff 4b)       bl      .*\.plt_call\.f1\+0x4>
+.*:    (4b ff .. ..|.. .. ff 4b)       bl      .*\.plt_call\.f2>
 #pass
diff --git a/ld/testsuite/ld-powerpc/callstub-4.d b/ld/testsuite/ld-powerpc/callstub-4.d
new file mode 100644 (file)
index 0000000..12ea0d9
--- /dev/null
@@ -0,0 +1,32 @@
+#source: callstub-1.s
+#as: -a64 -mpower10
+#ld: -melf64ppc -shared --plt-align=0 --hash-style=gnu
+#objdump: -dr -Mpower10
+
+.*
+
+Disassembly of section \.text:
+
+.*\.plt_call\.f1>:
+.*:    (04 10 00 01|01 00 10 04)       pld     r12,.*
+.*:    (e5 80 .. ..|.. .. 80 e5) 
+.*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*:    (4e 80 04 20|20 04 80 4e)       bctr
+.*:    (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 20|20 04 80 4e)       bctr
+
+.*\.plt_call\.f2>:
+.*:    (04 10 00 01|01 00 10 04)       pld     r12,.*
+.*:    (e5 80 .. ..|.. .. 80 e5) 
+.*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*:    (4e 80 04 20|20 04 80 4e)       bctr
+#...
+
+.*<_start>:
+.*:    (4b ff .. ..|.. .. ff 4b)       bl      .*\.plt_call\.f1\+0x10>
+.*:    (e8 41 00 18|18 00 41 e8)       ld      r2,24\(r1\)
+.*:    (4b ff .. ..|.. .. ff 4b)       bl      .*\.plt_call\.f1>
+.*:    (4b ff .. ..|.. .. ff 4b)       bl      .*\.plt_call\.f2>
+#pass
index eaafd01390526a5d722f45dfcd1c1fb4cf24e7fb..3555be7334c03b21e4c066662f5b5d1f978be82d 100644 (file)
@@ -1,6 +1,6 @@
 #source: notoc.s
 #as: -a64
-#ld: --no-plt-localentry -T ext.lnk
+#ld: --no-plt-localentry --no-power10-stubs -T ext.lnk
 #objdump: -d
 #target: powerpc64*-*-*
 
diff --git a/ld/testsuite/ld-powerpc/notoc3.d b/ld/testsuite/ld-powerpc/notoc3.d
new file mode 100644 (file)
index 0000000..ce19e99
--- /dev/null
@@ -0,0 +1,97 @@
+#as: -a64 -mpower10
+#ld: --no-plt-localentry -T ext.lnk
+#objdump: -d
+#target: powerpc64*-*-*
+
+.*
+
+Disassembly of section \.text:
+
+.* <.*\.long_branch\.f1>:
+.*:    (18 00 41 f8|f8 41 00 18)       std     r2,24\(r1\)
+.*:    (.. .. 00 48|48 00 .. ..)       b       .* <f1>
+
+.* <.*\.long_branch\.g1>:
+.*:    (18 00 41 f8|f8 41 00 18)       std     r2,24\(r1\)
+.*:    (.. .. 00 48|48 00 .. ..)       b       .* <g1>
+
+.* <.*\.plt_branch\.ext>:
+.*:    (00 20 60 3d|3d 60 20 00)       lis     r11,8192
+.*:    (00 00 6b 61|61 6b 00 00)       ori     r11,r11,0
+.*:    (ff ef 13 06|06 13 ef ff)       pla     r12,-268435736
+.*:    (e8 fe 80 39|39 80 fe e8) 
+.*:    (46 17 6b 79|79 6b 17 46)       rldicr  r11,r11,34,29
+.*:    (14 62 8b 7d|7d 8b 62 14)       add     r12,r11,r12
+.*:    (a6 03 89 7d|7d 89 03 a6)       mtctr   r12
+.*:    (20 04 80 4e|4e 80 04 20)       bctr
+.*:    (00 80 82 e9|e9 82 80 00)       ld      r12,-32768\(r2\)
+.*:    (a6 03 89 7d|7d 89 03 a6)       mtctr   r12
+.*:    (20 04 80 4e|4e 80 04 20)       bctr
+
+.* <.*\.long_branch\.f2>:
+.*:    (00 00 00 60|60 00 00 00)       nop
+.*:    (00 00 10 06|06 10 00 00)       pla     r12,108
+.*:    (6c 00 80 39|39 80 00 6c) 
+.*:    (.. .. 00 48|48 00 .. ..)       b       .* <f2>
+
+.* <.*\.long_branch\.g2>:
+.*:    (00 00 00 60|60 00 00 00)       nop
+.*:    (00 00 10 06|06 10 00 00)       pla     r12,144
+.*:    (90 00 80 39|39 80 00 90) 
+.*:    (.. .. 00 48|48 00 .. ..)       b       .* <g2>
+#...
+
+.* <f1>:
+.*:    (01 00 00 48|48 00 00 01)       bl      .* <f1>
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <.*\.long_branch\.f2>
+.*:    (.. .. 00 48|48 00 .. ..)       bl      .* <g1>
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <.*\.long_branch\.g2>
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <.*\.plt_branch\.ext>
+.*:    (20 00 80 4e|4e 80 00 20)       blr
+
+.* <g1>:
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <.*\.long_branch\.f2>
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <f1>
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <.*\.long_branch\.g2>
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <g1>
+.*:    (20 00 80 4e|4e 80 00 20)       blr
+
+.* <f2>:
+.*:    (02 10 40 3c|3c 40 10 02)       lis     r2,4098
+.*:    (00 90 42 38|38 42 90 00)       addi    r2,r2,-28672
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <.*\.long_branch\.f1>
+.*:    (18 00 41 e8|e8 41 00 18)       ld      r2,24\(r1\)
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <f2\+0x8>
+.*:    (00 00 00 60|60 00 00 00)       nop
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <.*\.long_branch\.g1>
+.*:    (18 00 41 e8|e8 41 00 18)       ld      r2,24\(r1\)
+.*:    (.. .. 00 48|48 00 .. ..)       bl      .* <g2\+0x8>
+.*:    (00 00 00 60|60 00 00 00)       nop
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <.*\.plt_branch\.ext\+0x20>
+.*:    (00 00 00 60|60 00 00 00)       nop
+.*:    (20 00 80 4e|4e 80 00 20)       blr
+
+.* <g2>:
+.*:    (02 10 40 3c|3c 40 10 02)       lis     r2,4098
+.*:    (00 90 42 38|38 42 90 00)       addi    r2,r2,-28672
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <f2\+0x8>
+.*:    (00 00 00 60|60 00 00 00)       nop
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <.*\.long_branch\.f1>
+.*:    (18 00 41 e8|e8 41 00 18)       ld      r2,24\(r1\)
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <g2\+0x8>
+.*:    (00 00 00 60|60 00 00 00)       nop
+.*:    (.. .. ff 4b|4b ff .. ..)       bl      .* <.*\.long_branch\.g1>
+.*:    (18 00 41 e8|e8 41 00 18)       ld      r2,24\(r1\)
+.*:    (20 00 80 4e|4e 80 00 20)       blr
+
+.* <_start>:
+.*:    (00 00 00 48|48 00 00 00)       b       .* <_start>
+#...
+
+Disassembly of section \.text\.ext:
+
+8000000000000000 <ext>:
+8000000000000000:      (02 10 40 3c|3c 40 10 02)       lis     r2,4098
+8000000000000004:      (00 90 42 38|38 42 90 00)       addi    r2,r2,-28672
+8000000000000008:      (00 00 00 60|60 00 00 00)       nop
+800000000000000c:      (20 00 80 4e|4e 80 00 20)       blr
diff --git a/ld/testsuite/ld-powerpc/notoc3.s b/ld/testsuite/ld-powerpc/notoc3.s
new file mode 100644 (file)
index 0000000..afbefa4
--- /dev/null
@@ -0,0 +1,59 @@
+ .text
+ .globl f1, f2, g1, g2, _start
+ .weak ext
+ .abiversion 2
+
+f1:
+ .localentry f1,1
+ bl f1@notoc
+ bl f2@notoc
+ bl g1@notoc
+ bl g2@notoc
+ bl ext@notoc
+ blr
+
+g1:
+ .localentry g1,1
+ bl f2@notoc
+ bl f1@notoc
+ bl g2@notoc
+ bl g1@notoc
+ blr
+
+f2:
+0:
+ addis 2,12,.TOC.-0b@ha
+ addi 2,2,.TOC.-0b@l
+ .localentry f2,.-0b
+ bl f1
+ nop
+ bl f2
+ nop
+ bl g1
+ nop
+ bl g2
+ nop
+ bl ext
+ nop
+ blr
+
+g2:
+0:
+ addis 2,12,.TOC.-0b@ha
+ addi 2,2,.TOC.-0b@l
+ .localentry g2,.-0b
+ bl f2
+ nop
+ bl f1
+ nop
+ bl g2
+ nop
+ bl g1
+ nop
+ blr
+
+_start:
+ .cfi_startproc
+ b _start
+ pld 3,_start
+ .cfi_endproc
diff --git a/ld/testsuite/ld-powerpc/notoc3.wf b/ld/testsuite/ld-powerpc/notoc3.wf
new file mode 100644 (file)
index 0000000..23904f8
--- /dev/null
@@ -0,0 +1,17 @@
+Contents of the \.eh_frame section:
+
+
+00000000 0000000000000010 00000000 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
+
+00000014 0000000000000010 00000018 FDE cie=00000000 pc=000000001000020c\.\.0000000010000218
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
index 93bef1c9c4e34523e176966a6b09746708e87a1e..bce99ef3c32c1d546152d12aa32758f4f554ae4b 100644 (file)
@@ -317,10 +317,14 @@ set ppc64elftests {
     {"ambig shared v1" "-shared -melf64ppc" "" "-a64" {funv1.s} {} "funv1.so"}
     {"ambig shared v2" "-shared -melf64ppc" "" "-a64" {funv2.s} {} "funv2.so"}
     {"notoc ext" "" "" "-a64" {ext.s} {} ""}
-    {"notoc" "-melf64ppc --no-plt-localentry -T ext.lnk" "" "-a64" {notoc.s}
+    {"notoc" "-melf64ppc --no-plt-localentry --no-power10-stubs -T ext.lnk"
+       "" "-a64" {notoc.s}
        {{objdump -d notoc.d} {readelf {-wf -W} notoc.wf}} "notoc"}
     {"notoc2" "-melf64ppc -shared" "" "-a64 -mpower10" {notoc2.s}
        {{objdump {-d -Mpower10} notoc2.d}} "notoc2"}
+    {"notoc3" "-melf64ppc --no-plt-localentry -T ext.lnk" ""
+       "-a64 -mpower10" {notoc3.s}
+       {{objdump -d notoc3.d} {readelf {-wf -W} notoc3.wf}} "notoc3"}
     {"pcrelopt" "-melf64ppc --hash-style=gnu" "tmpdir/symtocbase.so"
        "-a64 -mpower10" {pcrelopt.s}
        {{objdump {-d -Mpower10} pcrelopt.d}
@@ -403,6 +407,7 @@ if [ supports_ppc64 ] then {
     run_dump_test "callstub-1"
     run_dump_test "callstub-2"
     run_dump_test "callstub-3"
+    run_dump_test "callstub-4"
     run_dump_test "tlsgd"
     run_dump_test "tlsld"
     run_dump_test "tlsie"