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