These were docmented in [1] (with the user-facing name of the opcode adjusted later in [2]).
Since MSVC 2022, the precompiled runtimes (both runtimes such as vcruntime140*.dll and the statically linked code from e.g. libcmt.lib) are built with pointer authentication enabled.
To correctly handle unwinding through such functions, even on HW that don't support the pointer authentication mechanism itself, wine needs to at least be aware of it (for handling the cases with packed unwind info with CR==2 simiarly to CR==3).
This patch has been tested on Linux on HW supporting pointer authentication too, with binaries built with MSVC.
[1] https://github.com/MicrosoftDocs/cpp-docs/commit/f510c83085d9764b3c7b5222197... [2] https://github.com/MicrosoftDocs/cpp-docs/commit/cac237d3f370a06b71f6c314a67...
-- v2: ntdll: Handle aarch64 pointer authentication in unwind info
From: Martin Storsjö martin@martin.st
These were docmented in [1] (with the user-facing name of the opcode adjusted later in [2]).
Since MSVC 2022, the precompiled runtimes (both runtimes such as vcruntime140*.dll and the statically linked code from e.g. libcmt.lib) are built with pointer authentication enabled.
To correctly handle unwinding through such functions, even on HW that don't support the pointer authentication mechanism itself, wine needs to at least be aware of it (for handling the cases with packed unwind info with CR==2 simiarly to CR==3).
This patch has been tested on Linux on HW supporting pointer authentication too, with binaries built with MSVC.
[1] https://github.com/MicrosoftDocs/cpp-docs/commit/f510c83085d9764b3c7b5222197... [2] https://github.com/MicrosoftDocs/cpp-docs/commit/cac237d3f370a06b71f6c314a67... --- dlls/ntdll/signal_arm64.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index cadf774be67..257381e52a3 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -688,6 +688,20 @@ static void restore_fpregs( int reg, int count, int pos, CONTEXT *context, }
+static void do_pac_auth( CONTEXT *context ) +{ + register DWORD64 x17 __asm__( "x17" ) = context->u.s.Lr; + register DWORD64 x16 __asm__( "x16" ) = context->Sp; + + /* This is the autib1716 instruction. The hint instruction is used here + * as gcc does not assemble autib1716 for pre armv8.3a targets. For + * pre-armv8.3a targets, this is just treated as a hint instruction, which + * is ignored. */ + __asm__( "hint 0xe" : "+r"(x17) : "r"(x16) ); + + context->u.s.Lr = x17; +} + /*********************************************************************** * process_unwind_codes */ @@ -771,6 +785,10 @@ static void process_unwind_codes( BYTE *ptr, BYTE *end, CONTEXT *context, { memcpy( context, (DWORD64 *)context->Sp, sizeof(CONTEXT) ); } + else if (*ptr == 0xfc) /* pac_sign_lr */ + { + do_pac_auth( context ); + } else { WARN( "unsupported code %02x\n", *ptr ); @@ -818,6 +836,9 @@ static void *unwind_packed_data( ULONG_PTR base, ULONG_PTR pc, RUNTIME_FUNCTION len = (int_size + 8) / 16 + (fp_size + 8) / 16; switch (func->u.s.CR) { + case 2: + len++; /* pacibsp */ + /* fall through */ case 3: len++; /* mov x29,sp */ len++; /* stp x29,lr,[sp,0] */ @@ -843,7 +864,7 @@ static void *unwind_packed_data( ULONG_PTR base, ULONG_PTR pc, RUNTIME_FUNCTION
if (!skip) { - if (func->u.s.CR == 3) + if (func->u.s.CR == 3 || func->u.s.CR == 2) { DWORD64 *fp = (DWORD64 *) context->u.s.Fp; /* u.X[29] */ context->Sp = context->u.s.Fp; @@ -862,6 +883,7 @@ static void *unwind_packed_data( ULONG_PTR base, ULONG_PTR pc, RUNTIME_FUNCTION switch (func->u.s.CR) { case 3: + case 2: /* mov x29,sp */ if (pos++ >= skip) context->Sp = context->u.s.Fp; if (local_size <= 512) @@ -930,6 +952,7 @@ static void *unwind_packed_data( ULONG_PTR base, ULONG_PTR pc, RUNTIME_FUNCTION restore_regs( 19, 2, -saved_regs, context, ptrs ); } } + if (func->u.s.CR == 2) do_pac_auth( context ); return NULL; }