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.
This commit is contained in:
Alan Modra 2020-07-17 16:47:28 +09:30
parent 6095ca5257
commit e10a07b32d
13 changed files with 359 additions and 34 deletions

View 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 Alan Modra <amodra@gmail.com> 2020-07-15 Alan Modra <amodra@gmail.com>
PR 26239 PR 26239

View File

@ -3245,6 +3245,9 @@ struct ppc_link_hash_table
/* Whether calls are made via the PLT from NOTOC functions. */ /* Whether calls are made via the PLT from NOTOC functions. */
unsigned int notoc_plt:1; 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. */ /* Incremented every time we size stubs. */
unsigned int stub_iteration; unsigned int stub_iteration;
@ -3679,6 +3682,37 @@ ppc_stub_name (const asection *input_section,
return stub_name; 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 /* Look up an entry in the stub hash. Stub entries are cached because
creating the stub name takes a bit of time. */ creating the stub name takes a bit of time. */
@ -3723,6 +3757,13 @@ ppc_get_stub_entry (const asection *input_section,
free (stub_name); 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; 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:
case R_PPC64_PLT_PCREL34_NOTOC: case R_PPC64_PLT_PCREL34_NOTOC:
case R_PPC64_PCREL28: case R_PPC64_PCREL28:
if (htab->params->power10_stubs < 0) htab->has_power10_relocs = 1;
htab->params->power10_stubs = 1;
break; break;
default: default:
break; 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 (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 bfd_vma start = (stub_entry->stub_offset
+ stub_entry->group->stub_sec->output_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; relp = p;
num_rel = 0; 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; bfd_boolean load = stub_entry->stub_type >= ppc_stub_plt_call_notoc;
p = build_power10_offset (htab->params->stub_bfd, p, off, odd, load); 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) if (info->emitrelocations)
{ {
bfd_vma roff = relp - stub_entry->group->stub_sec->contents; 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); num_rel += num_relocs_for_power10_offset (off, odd);
else 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); r = get_relocs (stub_entry->group->stub_sec, num_rel);
if (r == NULL) if (r == NULL)
return FALSE; 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); r = emit_relocs_for_power10_offset (info, r, roff, targ, off, odd);
else else
r = emit_relocs_for_offset (info, r, roff, targ, off); 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 != NULL
&& htab->glink_eh_frame->size != 0) && 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) if (info->emitrelocations)
{ {
unsigned int num_rel; 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); num_rel = num_relocs_for_power10_offset (off, odd);
else else
num_rel = num_relocs_for_offset (off - 8); 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; 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); extra = size_power10_offset (off, odd);
else else
extra = size_offset (off - 8); extra = size_offset (off - 8);
@ -12036,7 +12076,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
calculated. */ calculated. */
off -= extra; 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 /* After the bcl, lr has been modified so we need to emit
.eh_frame info saying the return address is in r12. */ .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) if (info->emitrelocations)
{ {
unsigned int num_rel; 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); num_rel = num_relocs_for_power10_offset (off, odd);
else else
num_rel = num_relocs_for_offset (off - 8); 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); 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 /* After the bcl, lr has been modified so we need to emit
.eh_frame info saying the return address is in r12. */ .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) if (htab == NULL)
return FALSE; 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)) if (htab->params->plt_thread_safe == -1 && !bfd_link_executable (info))
htab->params->plt_thread_safe = 1; htab->params->plt_thread_safe = 1;
if (!htab->opd_abi) if (!htab->opd_abi)
@ -13409,6 +13452,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
if (stub_entry != NULL) if (stub_entry != NULL)
{ {
enum ppc_stub_type old_type; enum ppc_stub_type old_type;
/* A stub has already been created, but it may /* A stub has already been created, but it may
not be the required type. We shouldn't be not be the required type. We shouldn't be
transitioning from plt_call to long_branch 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 upgrading from plt_call to plt_call_r2save or
from long_branch to long_branch_r2off. */ from long_branch to long_branch_r2off. */
free (stub_name); 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; old_type = stub_entry->stub_type;
switch (old_type) switch (old_type)
{ {

View 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-17 Hans-Peter Nilsson <hp@bitrange.com> 2020-07-17 Hans-Peter Nilsson <hp@bitrange.com>
* scripttempt/mmo.sc: Move .init first in .text output section. * scripttempt/mmo.sc: Move .init first in .text output section.

View File

@ -716,7 +716,7 @@ PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}'
{ "no-plt-align", no_argument, NULL, OPTION_NO_PLT_ALIGN }, { "no-plt-align", no_argument, NULL, OPTION_NO_PLT_ALIGN },
{ "plt-localentry", optional_argument, NULL, OPTION_PLT_LOCALENTRY }, { "plt-localentry", optional_argument, NULL, OPTION_PLT_LOCALENTRY },
{ "no-plt-localentry", no_argument, NULL, OPTION_NO_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 }, { "no-power10-stubs", no_argument, NULL, OPTION_NO_POWER10_STUBS },
{ "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS }, { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS },
{ "no-emit-stub-syms", no_argument, NULL, OPTION_NO_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" --no-plt-localentry Don'\''t optimize ELFv2 calls\n"
)); ));
fprintf (file, _("\ 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, _("\ fprintf (file, _("\
--no-power10-stubs Don'\''t use Power10 PLT call stubs\n" --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; break;
case OPTION_POWER10_STUBS: 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; break;
case OPTION_NO_POWER10_STUBS: case OPTION_NO_POWER10_STUBS:

View File

@ -7922,15 +7922,13 @@ care. @option{--no-plt-localentry} is the default.
@itemx --no-power10-stubs @itemx --no-power10-stubs
When PowerPC64 @command{ld} links input object files containing When PowerPC64 @command{ld} links input object files containing
relocations used on power10 prefixed instructions it normally creates relocations used on power10 prefixed instructions it normally creates
linkage stubs (PLT call and long branch) using power10 instructions. linkage stubs (PLT call and long branch) using power10 instructions
In particular for @code{@@notoc} PLT calls where @code{r2} is not for @code{@@notoc} PLT calls where @code{r2} is not known. The
known the power10 stubs are smaller and faster, so are preferred for power10 notoc stubs are smaller and faster, so are preferred for
power10. @option{--power10-stubs} and @option{--no-power10-stubs} power10. @option{--power10-stubs} and @option{--no-power10-stubs}
allow you to override the linker's selection of stub instructions. allow you to override the linker's selection of stub instructions.
For example, when linking a shared library that contains cpu-optimized @option{--power10-stubs=auto} allows the user to select the default
versions of functions for both power9 and power10, you might use auto mode.
@option{--no-power10-stubs} so that power9 code making calls doesn't
attempt to execute power10 instructions.
@end table @end table
@ifclear GENERIC @ifclear GENERIC

View File

@ -1,5 +1,5 @@
#as: -a64 -mpower10 #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 #objdump: -dr -Mpower10
.* .*
@ -20,10 +20,10 @@ Disassembly of section \.text:
.*: (7d 89 03 a6|a6 03 89 7d) mtctr r12 .*: (7d 89 03 a6|a6 03 89 7d) mtctr r12
.*: (4e 80 04 20|20 04 80 4e) bctr .*: (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\) .*: (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 4b) bl .*\.plt_call\.f1\+0x4>
.*: (4b ff ff cd|cd ff ff 4b) bl .*\.plt_call\.f2> .*: (4b ff .. ..|.. .. ff 4b) bl .*\.plt_call\.f2>
.*: (04 10 00 01|01 00 10 04) pld r3,.*
.*: (e4 60 .. ..|.. .. 60 e4)
#pass #pass

View File

@ -27,9 +27,9 @@ Disassembly of section \.text:
.*: (7d 89 03 a6|a6 03 89 7d) mtctr r12 .*: (7d 89 03 a6|a6 03 89 7d) mtctr r12
.*: (4e 80 04 20|20 04 80 4e) bctr .*: (4e 80 04 20|20 04 80 4e) bctr
#... .*<_start>:
.*: (4b ff ff bd|bd ff ff 4b) bl .*\.plt_call\.f1> .*: (4b ff .. ..|.. .. ff 4b) bl .*\.plt_call\.f1>
.*: (e8 41 00 18|18 00 41 e8) ld r2,24\(r1\) .*: (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 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\.f2>
#pass #pass

View File

@ -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

View File

@ -1,6 +1,6 @@
#source: notoc.s #source: notoc.s
#as: -a64 #as: -a64
#ld: --no-plt-localentry -T ext.lnk #ld: --no-plt-localentry --no-power10-stubs -T ext.lnk
#objdump: -d #objdump: -d
#target: powerpc64*-*-* #target: powerpc64*-*-*

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -317,10 +317,14 @@ set ppc64elftests {
{"ambig shared v1" "-shared -melf64ppc" "" "-a64" {funv1.s} {} "funv1.so"} {"ambig shared v1" "-shared -melf64ppc" "" "-a64" {funv1.s} {} "funv1.so"}
{"ambig shared v2" "-shared -melf64ppc" "" "-a64" {funv2.s} {} "funv2.so"} {"ambig shared v2" "-shared -melf64ppc" "" "-a64" {funv2.s} {} "funv2.so"}
{"notoc ext" "" "" "-a64" {ext.s} {} ""} {"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"} {{objdump -d notoc.d} {readelf {-wf -W} notoc.wf}} "notoc"}
{"notoc2" "-melf64ppc -shared" "" "-a64 -mpower10" {notoc2.s} {"notoc2" "-melf64ppc -shared" "" "-a64 -mpower10" {notoc2.s}
{{objdump {-d -Mpower10} notoc2.d}} "notoc2"} {{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" {"pcrelopt" "-melf64ppc --hash-style=gnu" "tmpdir/symtocbase.so"
"-a64 -mpower10" {pcrelopt.s} "-a64 -mpower10" {pcrelopt.s}
{{objdump {-d -Mpower10} pcrelopt.d} {{objdump {-d -Mpower10} pcrelopt.d}
@ -403,6 +407,7 @@ if [ supports_ppc64 ] then {
run_dump_test "callstub-1" run_dump_test "callstub-1"
run_dump_test "callstub-2" run_dump_test "callstub-2"
run_dump_test "callstub-3" run_dump_test "callstub-3"
run_dump_test "callstub-4"
run_dump_test "tlsgd" run_dump_test "tlsgd"
run_dump_test "tlsld" run_dump_test "tlsld"
run_dump_test "tlsie" run_dump_test "tlsie"