Commit 7f7f06fe authored by Martin Storsjö's avatar Martin Storsjö Committed by Alexandre Julliard

ntdll: Handle aarch64 pointer authentication in unwind info.

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/f510c83085d9764b3c7b52221978af266d54e397 [2] https://github.com/MicrosoftDocs/cpp-docs/commit/cac237d3f370a06b71f6c314a67e7acdfab568fd
parent 26163c10
......@@ -690,6 +690,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
*/
......@@ -773,6 +787,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 );
......@@ -820,6 +838,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] */
......@@ -845,7 +866,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;
......@@ -864,6 +885,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)
......@@ -932,6 +954,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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment