PowerPC64 ld --no-power10-stubs

Fangrui Song i@maskray.me
Fri Jul 10 04:23:06 GMT 2020


On 2020-07-10, Alan Modra via Binutils wrote:
>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.
>
>diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
>index 8d710848ba..e54f561019 100644
>--- a/bfd/elf64-ppc.c
>+++ b/bfd/elf64-ppc.c
>@@ -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.  */
>diff --git a/bfd/elf64-ppc.h b/bfd/elf64-ppc.h
>index a2ffd4eb72..547971f8be 100644
>--- a/bfd/elf64-ppc.h
>+++ b/bfd/elf64-ppc.h
>@@ -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;
>diff --git a/ld/ChangeLog b/ld/ChangeLog
>index 14f31a805f..b9c844ced3 100644
>--- a/ld/ChangeLog
>+++ b/ld/ChangeLog
>@@ -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.
>diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em
>index a2834c8525..4987243fa1 100644
>--- a/ld/emultempl/ppc64elf.em
>+++ b/ld/emultempl/ppc64elf.em
>@@ -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
>index 0000000000..06cbfbda4a
>--- /dev/null
>+++ b/ld/testsuite/ld-powerpc/callstub-3.d
>@@ -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
>diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
>index de676b8176..50553baa90 100644
>--- a/ld/testsuite/ld-powerpc/powerpc.exp
>+++ b/ld/testsuite/ld-powerpc/powerpc.exp
>@@ -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"
>
>-- 
>Alan Modra
>Australia Development Lab, IBM

ELF specific options usually start with -z.

IMHO the name "--no-power10-stubs" does not get to the point. Why is
power10 special? The feature X (which is enabled on power10) is the
thing that is special. The option should just mention X.

The documentation does not seem to be updated.

(I have been waiting for an ABI for a while. Apparently
http://lists.mailinglist.openpowerfoundation.org/pipermail/syssw-elfv2abi/
hasn't been updated for the past 3 months.)


More information about the Binutils mailing list