PowerPC64 ld --no-power10-stubs
authorAlan Modra <amodra@gmail.com>
Fri, 10 Jul 2020 01:18:45 +0000 (10:48 +0930)
committerAlan Modra <amodra@gmail.com>
Fri, 10 Jul 2020 01:44:38 +0000 (11:14 +0930)
Needed for libraries that use ifuncs or other means to support
cpu-optimized versions of functions, some power10, some not, and those
functions make calls using linkage stubs.

bfd/
* elf64-ppc.h (struct ppc64_elf_params): Add power10_stubs.
* elf64-ppc.c (struct ppc_link_hash_table): Delete
power10_stubs.
(ppc64_elf_check_relocs): Adjust setting of power10_stubs.
(plt_stub_size, ppc_build_one_stub, ppc_size_one_stub): Adjust
uses of power10_stubs.
ld/
* emultempl/ppc64elf.em (params): Init new field.
(enum ppc64_opt): Add OPTION_POWER10_STUBS and OPTION_NO_POWER10_STUBS.
(PARSE_AND_LIST_LONGOPTS): Support --power10-stubs and
--no-power10-stubs.
(PARSE_AND_LIST_OPTIONS, PARSE_AND_LIST_ARGS_CASES): Likewise.
* testsuite/ld-powerpc/callstub-3.d: New test.
* testsuite/ld-powerpc/powerpc.exp: Run it.

bfd/ChangeLog
bfd/elf64-ppc.c
bfd/elf64-ppc.h
ld/ChangeLog
ld/emultempl/ppc64elf.em
ld/testsuite/ld-powerpc/callstub-3.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/powerpc.exp

index afbccc3fa50ef4bb7271a7e0ec255dfbb43b9964..3cb4881febc9d9b9b072c96143a6d75a5d4a9d6a 100644 (file)
@@ -1,3 +1,12 @@
+2020-07-10  Alan Modra  <amodra@gmail.com>
+
+       * elf64-ppc.h (struct ppc64_elf_params): Add power10_stubs.
+       * elf64-ppc.c (struct ppc_link_hash_table): Delete
+       power10_stubs.
+       (ppc64_elf_check_relocs): Adjust setting of power10_stubs.
+       (plt_stub_size, ppc_build_one_stub, ppc_size_one_stub): Adjust
+       uses of power10_stubs.
+
 2020-07-09  Alan Modra  <amodra@gmail.com>
 
        * coff-ppc.c: Delete.
index 8d710848ba60bd89ab5c5ef039d01cd7c4208a66..e54f561019410a0454a5cd21eb48b107ca92630b 100644 (file)
@@ -3245,9 +3245,6 @@ struct ppc_link_hash_table
   /* Whether calls are made via the PLT from NOTOC functions.  */
   unsigned int notoc_plt:1;
 
-  /* Whether to use power10 instructions in linkage stubs.  */
-  unsigned int power10_stubs:1;
-
   /* Incremented every time we size stubs.  */
   unsigned int stub_iteration;
 
@@ -4602,7 +4599,8 @@ 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:
-         htab->power10_stubs = 1;
+         if (htab->params->power10_stubs < 0)
+           htab->params->power10_stubs = 1;
          break;
        default:
          break;
@@ -10763,7 +10761,7 @@ plt_stub_size (struct ppc_link_hash_table *htab,
 
   if (stub_entry->stub_type >= ppc_stub_plt_call_notoc)
     {
-      if (htab->power10_stubs)
+      if (htab->params->power10_stubs > 0)
        {
          bfd_vma start = (stub_entry->stub_offset
                           + stub_entry->group->stub_sec->output_offset
@@ -11604,7 +11602,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       relp = p;
       num_rel = 0;
-      if (htab->power10_stubs)
+      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);
@@ -11643,7 +11641,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->power10_stubs)
+         if (htab->params->power10_stubs > 0)
            num_rel += num_relocs_for_power10_offset (off, odd);
          else
            {
@@ -11653,7 +11651,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->power10_stubs)
+         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);
@@ -11671,7 +11669,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
            }
        }
 
-      if (!htab->power10_stubs
+      if (htab->params->power10_stubs <= 0
          && htab->glink_eh_frame != NULL
          && htab->glink_eh_frame->size != 0)
        {
@@ -12019,7 +12017,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (info->emitrelocations)
        {
          unsigned int num_rel;
-         if (htab->power10_stubs)
+         if (htab->params->power10_stubs > 0)
            num_rel = num_relocs_for_power10_offset (off, odd);
          else
            num_rel = num_relocs_for_offset (off - 8);
@@ -12027,7 +12025,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
          stub_entry->group->stub_sec->flags |= SEC_RELOC;
        }
 
-      if (htab->power10_stubs)
+      if (htab->params->power10_stubs > 0)
        extra = size_power10_offset (off, odd);
       else
        extra = size_offset (off - 8);
@@ -12038,7 +12036,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
         calculated.  */
       off -= extra;
 
-      if (!htab->power10_stubs)
+      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.  */
@@ -12101,7 +12099,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (info->emitrelocations)
        {
          unsigned int num_rel;
-         if (htab->power10_stubs)
+         if (htab->params->power10_stubs > 0)
            num_rel = num_relocs_for_power10_offset (off, odd);
          else
            num_rel = num_relocs_for_offset (off - 8);
@@ -12111,7 +12109,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       size = plt_stub_size (htab, stub_entry, off);
 
-      if (!htab->power10_stubs)
+      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.  */
index a2ffd4eb72ef56db0aa87d7dd37751dbee2fbf08..547971f8becad2a23c64aeccf12f21dfca8a5fdd 100644 (file)
@@ -54,6 +54,9 @@ struct ppc64_elf_params
   /* Set if PLT call stubs for localentry:0 functions should omit r2 save.  */
   int plt_localentry0;
 
+  /* Whether to use power10 instructions in linkage stubs.  */
+  int power10_stubs;
+
   /* Whether to canonicalize .opd so that there are no overlapping
      .opd entries.  */
   int non_overlapping_opd;
index 14f31a805f5926ff93ad93caf4738997cfced90b..b9c844ced362dbbdacc60701fee39b8abbfc3b41 100644 (file)
@@ -1,3 +1,13 @@
+2020-07-10  Alan Modra  <amodra@gmail.com>
+
+       * emultempl/ppc64elf.em (params): Init new field.
+       (enum ppc64_opt): Add OPTION_POWER10_STUBS and OPTION_NO_POWER10_STUBS.
+       (PARSE_AND_LIST_LONGOPTS): Support --power10-stubs and
+       --no-power10-stubs.
+       (PARSE_AND_LIST_OPTIONS, PARSE_AND_LIST_ARGS_CASES): Likewise.
+       * testsuite/ld-powerpc/callstub-3.d: New test.
+       * testsuite/ld-powerpc/powerpc.exp: Run it.
+
 2020-07-09  Alan Modra  <amodra@gmail.com>
 
        * emulparams/ppcpe.sh: Delete.
index a2834c8525730503d4bb49837d2280492c7ba0e6..4987243fa1e361a2b50b67f2c68bb60a03cb5b00 100644 (file)
@@ -38,7 +38,7 @@ static struct ppc64_elf_params params = { NULL,
                                          &ppc_layout_sections_again,
                                          1, -1, -1, 0,
                                          ${DEFAULT_PLT_STATIC_CHAIN-0}, -1, 5,
-                                         -1, 0, -1, -1, 0};
+                                         -1, -1, 0, -1, -1, 0};
 
 /* Fake input file for stubs.  */
 static lang_input_statement_type *stub_file;
@@ -684,6 +684,8 @@ enum ppc64_opt
   OPTION_NO_PLT_ALIGN,
   OPTION_PLT_LOCALENTRY,
   OPTION_NO_PLT_LOCALENTRY,
+  OPTION_POWER10_STUBS,
+  OPTION_NO_POWER10_STUBS,
   OPTION_STUBSYMS,
   OPTION_NO_STUBSYMS,
   OPTION_SAVRES,
@@ -714,6 +716,8 @@ 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 },
+  { "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 },
   { "dotsyms", no_argument, NULL, OPTION_DOTSYMS },
@@ -769,6 +773,12 @@ 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"
+                  ));
+  fprintf (file, _("\
+  --no-power10-stubs          Don'\''t use Power10 PLT call stubs\n"
+                  ));
+  fprintf (file, _("\
   --emit-stub-syms            Label linker stubs with a symbol\n"
                   ));
   fprintf (file, _("\
@@ -878,6 +888,14 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
       params.plt_localentry0 = 0;
       break;
 
+    case OPTION_POWER10_STUBS:
+      params.power10_stubs = 1;
+      break;
+
+    case OPTION_NO_POWER10_STUBS:
+      params.power10_stubs = 0;
+      break;
+
     case OPTION_STUBSYMS:
       params.emit_stub_syms = 1;
       break;
diff --git a/ld/testsuite/ld-powerpc/callstub-3.d b/ld/testsuite/ld-powerpc/callstub-3.d
new file mode 100644 (file)
index 0000000..06cbfbd
--- /dev/null
@@ -0,0 +1,38 @@
+#source: callstub-1.s
+#as: -a64 -mpower10
+#ld: -melf64ppc -shared --plt-align=0 --hash-style=gnu --no-power10-stubs
+#objdump: -dr -Mpower10
+
+.*
+
+Disassembly of section \.text:
+
+.*\.plt_call\.f1>:
+.*:    (f8 41 00 18|18 00 41 f8)       std     r2,24\(r1\)
+.*:    (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
+.*:    (7d 88 03 a6|a6 03 88 7d)       mtlr    r12
+.*:    (3d 8b 00 01|01 00 8b 3d)       addis   r12,r11,1
+.*:    (e9 8c .. ..|.. .. 8c e9)       ld      r12,.*\(r12\)
+.*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*:    (4e 80 04 20|20 04 80 4e)       bctr
+
+.*\.plt_call\.f2>:
+.*:    (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
+.*:    (7d 88 03 a6|a6 03 88 7d)       mtlr    r12
+.*:    (3d 8b 00 01|01 00 8b 3d)       addis   r12,r11,1
+.*:    (e9 8c .. ..|.. .. 8c e9)       ld      r12,.*\(r12\)
+.*:    (7d 89 03 a6|a6 03 89 7d)       mtctr   r12
+.*:    (4e 80 04 20|20 04 80 4e)       bctr
+
+#...
+.*:    (4b ff ff 81|81 ff ff 4b)       bl      .*\.plt_call\.f1>
+.*:    (e8 41 00 18|18 00 41 e8)       ld      r2,24\(r1\)
+.*:    (4b ff ff 7d|7d ff ff 4b)       bl      .*\.plt_call\.f1\+0x4>
+.*:    (4b ff ff 99|99 ff ff 4b)       bl      .*\.plt_call\.f2>
+.*:    (04 10 00 01|01 00 10 04)       pld     r3,.*
+.*:    (e4 60 .. ..|.. .. 60 e4) 
+#pass
index de676b81765a2961bed666d31f9800e7b480861a..50553baa90266c3b31875eb6855f979d3d9c6c99 100644 (file)
@@ -402,6 +402,7 @@ if [ supports_ppc64 ] then {
     run_dump_test "pr23937"
     run_dump_test "callstub-1"
     run_dump_test "callstub-2"
+    run_dump_test "callstub-3"
     run_dump_test "tlsgd"
     run_dump_test "tlsld"
     run_dump_test "tlsie"