From d349c8e245767249ce731965d082b994a5aa651a Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Fri, 17 Jul 2020 16:47:28 +0930 Subject: [PATCH] Power10 stub selection 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) --- bfd/ChangeLog | 13 ++++ bfd/elf64-ppc.c | 101 +++++++++++++++++++++++---- ld/ChangeLog | 14 ++++ ld/emultempl/ppc64elf.em | 19 ++++- ld/ld.texi | 12 ++-- ld/testsuite/ld-powerpc/callstub-1.d | 12 ++-- ld/testsuite/ld-powerpc/callstub-2.d | 8 +-- ld/testsuite/ld-powerpc/callstub-4.d | 32 +++++++++ ld/testsuite/ld-powerpc/notoc.d | 2 +- ld/testsuite/ld-powerpc/notoc3.d | 97 +++++++++++++++++++++++++ ld/testsuite/ld-powerpc/notoc3.s | 59 ++++++++++++++++ ld/testsuite/ld-powerpc/notoc3.wf | 17 +++++ ld/testsuite/ld-powerpc/powerpc.exp | 7 +- 13 files changed, 359 insertions(+), 34 deletions(-) create mode 100644 ld/testsuite/ld-powerpc/callstub-4.d create mode 100644 ld/testsuite/ld-powerpc/notoc3.d create mode 100644 ld/testsuite/ld-powerpc/notoc3.s create mode 100644 ld/testsuite/ld-powerpc/notoc3.wf diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 1a25c8e99c8..631493e235d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2020-07-19 Alan Modra + + * 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 * elf64-mmix.c (mmix_elf_relax_section): Improve accounting for diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index e54f5610194..8d622fb9092 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -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) { diff --git a/ld/ChangeLog b/ld/ChangeLog index 2985f105306..ca61ce291d6 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,17 @@ +2020-07-19 Alan Modra + + * 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 * testsuite/ld-mmix/undef-1.d, testsuite/ld-mmix/undef-1m.d, diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index 4987243fa1e..1331d03113b 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -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: diff --git a/ld/ld.texi b/ld/ld.texi index 165a3d935e1..2a93e9456ac 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -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 diff --git a/ld/testsuite/ld-powerpc/callstub-1.d b/ld/testsuite/ld-powerpc/callstub-1.d index 21eea767844..48efdfba0fa 100644 --- a/ld/testsuite/ld-powerpc/callstub-1.d +++ b/ld/testsuite/ld-powerpc/callstub-1.d @@ -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 diff --git a/ld/testsuite/ld-powerpc/callstub-2.d b/ld/testsuite/ld-powerpc/callstub-2.d index 603670710a5..5b43783aae1 100644 --- a/ld/testsuite/ld-powerpc/callstub-2.d +++ b/ld/testsuite/ld-powerpc/callstub-2.d @@ -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 index 00000000000..12ea0d9be03 --- /dev/null +++ b/ld/testsuite/ld-powerpc/callstub-4.d @@ -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 diff --git a/ld/testsuite/ld-powerpc/notoc.d b/ld/testsuite/ld-powerpc/notoc.d index eaafd013905..3555be7334c 100644 --- a/ld/testsuite/ld-powerpc/notoc.d +++ b/ld/testsuite/ld-powerpc/notoc.d @@ -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 index 00000000000..ce19e994bbe --- /dev/null +++ b/ld/testsuite/ld-powerpc/notoc3.d @@ -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 .* + +.* <.*\.long_branch\.g1>: +.*: (18 00 41 f8|f8 41 00 18) std r2,24\(r1\) +.*: (.. .. 00 48|48 00 .. ..) b .* + +.* <.*\.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 .* + +.* <.*\.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 .* +#... + +.* : +.*: (01 00 00 48|48 00 00 01) bl .* +.*: (.. .. ff 4b|4b ff .. ..) bl .* <.*\.long_branch\.f2> +.*: (.. .. 00 48|48 00 .. ..) bl .* +.*: (.. .. 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 + +.* : +.*: (.. .. ff 4b|4b ff .. ..) bl .* <.*\.long_branch\.f2> +.*: (.. .. ff 4b|4b ff .. ..) bl .* +.*: (.. .. ff 4b|4b ff .. ..) bl .* <.*\.long_branch\.g2> +.*: (.. .. ff 4b|4b ff .. ..) bl .* +.*: (20 00 80 4e|4e 80 00 20) blr + +.* : +.*: (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 .* +.*: (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 .* +.*: (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 + +.* : +.*: (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 .* +.*: (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 .* +.*: (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 : +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 index 00000000000..afbefa4a3ca --- /dev/null +++ b/ld/testsuite/ld-powerpc/notoc3.s @@ -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 index 00000000000..23904f83b99 --- /dev/null +++ b/ld/testsuite/ld-powerpc/notoc3.wf @@ -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 + diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp index 93bef1c9c4e..bce99ef3c32 100644 --- a/ld/testsuite/ld-powerpc/powerpc.exp +++ b/ld/testsuite/ld-powerpc/powerpc.exp @@ -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" -- 2.39.2