ntdll: Always set non-volatile pointers for ARM64 unwinding.
This commit is contained in:
parent
14a290e77d
commit
af4ef5fa02
2 changed files with 44 additions and 28 deletions
|
@ -8119,6 +8119,7 @@ struct unwind_test
|
|||
const struct results *results;
|
||||
unsigned int nb_results;
|
||||
int unwound_clear;
|
||||
int last_set_reg_ptr;
|
||||
};
|
||||
|
||||
enum regs
|
||||
|
@ -8170,7 +8171,7 @@ static void call_virtual_unwind( int testnum, const struct unwind_test *test )
|
|||
for (i = 0; i < test->nb_results; i++)
|
||||
{
|
||||
winetest_push_context( "%u/%u", testnum, i );
|
||||
memset( &ctx_ptr, 0, sizeof(ctx_ptr) );
|
||||
memset( &ctx_ptr, 0x55, sizeof(ctx_ptr) );
|
||||
memset( &context, 0x55, sizeof(context) );
|
||||
memset( &unset_reg, 0x55, sizeof(unset_reg) );
|
||||
for (j = 0; j < 256; j++) fake_stack[j] = j * 8;
|
||||
|
@ -8255,17 +8256,27 @@ static void call_virtual_unwind( int testnum, const struct unwind_test *test )
|
|||
if (test->results[i].regs[k][0] == j) break;
|
||||
}
|
||||
|
||||
if (regptr)
|
||||
ok( k < nb_regs, "register %s should not be set to %llx\n", reg_names[j], regval );
|
||||
|
||||
if (k < nb_regs)
|
||||
{
|
||||
ok( regval == test->results[i].regs[k][1],
|
||||
"register %s wrong %llx/%llx\n", reg_names[j], regval, test->results[i].regs[k][1] );
|
||||
if (regptr)
|
||||
{
|
||||
if (test->last_set_reg_ptr && j > test->last_set_reg_ptr && j <= 30)
|
||||
ok( regptr == (void *)unset_reg, "register %s should not have pointer set\n", reg_names[j] );
|
||||
else
|
||||
{
|
||||
ok( regptr != (void *)unset_reg, "register %s should have pointer set\n", reg_names[j] );
|
||||
if (regptr != (void *)unset_reg)
|
||||
ok( *regptr == regval, "register %s should have reg pointer to %llx / %llx\n",
|
||||
reg_names[j], *regptr, regval );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ok( k == nb_regs, "register %s should be set\n", reg_names[j] );
|
||||
ok( !regptr || regptr == (void *)unset_reg, "register %s should not have pointer set\n", reg_names[j] );
|
||||
if (j == lr)
|
||||
ok( context.Lr == ORIG_LR, "register lr wrong %llx/unset\n", context.Lr );
|
||||
else if (j == x29)
|
||||
|
@ -9052,26 +9063,26 @@ static void test_virtual_unwind(void)
|
|||
|
||||
static const struct unwind_test tests[] =
|
||||
{
|
||||
#define TEST(func, unwind, unwind_packed, results, unwound_clear) \
|
||||
{ func, sizeof(func), unwind, unwind_packed ? 0 : sizeof(unwind), results, ARRAY_SIZE(results), unwound_clear }
|
||||
TEST(function_0, unwind_info_0, 0, results_0, 0),
|
||||
TEST(function_1, unwind_info_1, 1, results_1, 0),
|
||||
TEST(function_2, unwind_info_2, 0, results_2, 1),
|
||||
TEST(function_3, unwind_info_3, 0, results_3, 1),
|
||||
TEST(function_4, unwind_info_4, 0, results_4, 0),
|
||||
TEST(function_5, unwind_info_5, 0, results_5, 0),
|
||||
TEST(function_6, unwind_info_6, 1, results_6, 0),
|
||||
TEST(function_7, unwind_info_7, 1, results_7, 0),
|
||||
TEST(function_8, unwind_info_8, 1, results_8, 0),
|
||||
TEST(function_9, unwind_info_9, 1, results_9, 0),
|
||||
TEST(function_10, unwind_info_10, 1, results_10, 0),
|
||||
TEST(function_11, unwind_info_11, 1, results_11, 0),
|
||||
TEST(function_12, unwind_info_12, 1, results_12, 0),
|
||||
TEST(function_13, unwind_info_13, 1, results_13, 0),
|
||||
TEST(function_14, unwind_info_14, 0, results_14, 0),
|
||||
TEST(function_15, unwind_info_15, 0, results_15, 0),
|
||||
TEST(function_16, unwind_info_16, 0, results_16, 1),
|
||||
TEST(function_17, unwind_info_17, 0, results_17, 2),
|
||||
#define TEST(func, unwind, unwind_packed, results, unwound_clear, last_ptr) \
|
||||
{ func, sizeof(func), unwind, unwind_packed ? 0 : sizeof(unwind), results, ARRAY_SIZE(results), unwound_clear, last_ptr }
|
||||
TEST(function_0, unwind_info_0, 0, results_0, 0, 0),
|
||||
TEST(function_1, unwind_info_1, 1, results_1, 0, 0),
|
||||
TEST(function_2, unwind_info_2, 0, results_2, 1, 0),
|
||||
TEST(function_3, unwind_info_3, 0, results_3, 1, x28),
|
||||
TEST(function_4, unwind_info_4, 0, results_4, 0, 0),
|
||||
TEST(function_5, unwind_info_5, 0, results_5, 0, 0),
|
||||
TEST(function_6, unwind_info_6, 1, results_6, 0, 0),
|
||||
TEST(function_7, unwind_info_7, 1, results_7, 0, 0),
|
||||
TEST(function_8, unwind_info_8, 1, results_8, 0, 0),
|
||||
TEST(function_9, unwind_info_9, 1, results_9, 0, 0),
|
||||
TEST(function_10, unwind_info_10, 1, results_10, 0, 0),
|
||||
TEST(function_11, unwind_info_11, 1, results_11, 0, 0),
|
||||
TEST(function_12, unwind_info_12, 1, results_12, 0, 0),
|
||||
TEST(function_13, unwind_info_13, 1, results_13, 0, 0),
|
||||
TEST(function_14, unwind_info_14, 0, results_14, 0, 0),
|
||||
TEST(function_15, unwind_info_15, 0, results_15, 0, 0),
|
||||
TEST(function_16, unwind_info_16, 0, results_16, 1, x18),
|
||||
TEST(function_17, unwind_info_17, 0, results_17, 2, 0),
|
||||
#undef TEST
|
||||
};
|
||||
unsigned int i;
|
||||
|
|
|
@ -388,7 +388,7 @@ static void do_pac_auth( ARM64_NT_CONTEXT *context )
|
|||
static void process_unwind_codes( BYTE *ptr, BYTE *end, ARM64_NT_CONTEXT *context,
|
||||
KNONVOLATILE_CONTEXT_POINTERS_ARM64 *ptrs, int skip )
|
||||
{
|
||||
unsigned int val, len, save_next = 2;
|
||||
unsigned int i, val, len, save_next = 2;
|
||||
|
||||
/* skip codes */
|
||||
while (ptr < end && skip)
|
||||
|
@ -473,6 +473,11 @@ static void process_unwind_codes( BYTE *ptr, BYTE *end, ARM64_NT_CONTEXT *contex
|
|||
ARM64_NT_CONTEXT *src_ctx = (ARM64_NT_CONTEXT *)context->Sp;
|
||||
*context = *src_ctx;
|
||||
context->ContextFlags = flags | (src_ctx->ContextFlags & CONTEXT_UNWOUND_TO_CALL);
|
||||
if (ptrs)
|
||||
{
|
||||
for (i = 19; i < 29; i++) (&ptrs->X19)[i - 19] = &src_ctx->X[i];
|
||||
for (i = 8; i < 16; i++) (&ptrs->D8)[i - 8] = &src_ctx->V[i].Low;
|
||||
}
|
||||
}
|
||||
else if (*ptr == 0xeb) /* MSFT_OP_EC_CONTEXT */
|
||||
{
|
||||
|
@ -480,6 +485,7 @@ static void process_unwind_codes( BYTE *ptr, BYTE *end, ARM64_NT_CONTEXT *contex
|
|||
ARM64EC_NT_CONTEXT *src_ctx = (ARM64EC_NT_CONTEXT *)context->Sp;
|
||||
context_x64_to_arm( context, src_ctx );
|
||||
context->ContextFlags = flags | (src_ctx->ContextFlags & CONTEXT_UNWOUND_TO_CALL);
|
||||
if (ptrs) for (i = 8; i < 16; i++) (&ptrs->D8)[i - 8] = &src_ctx->V[i].Low;
|
||||
}
|
||||
else if (*ptr == 0xec) /* MSFT_OP_CLEAR_UNWOUND_TO_CALL */
|
||||
{
|
||||
|
@ -562,10 +568,9 @@ static void *unwind_packed_data( ULONG_PTR base, ULONG_PTR pc, ARM64_RUNTIME_FUN
|
|||
{
|
||||
if (func->CR == 3 || func->CR == 2)
|
||||
{
|
||||
DWORD64 *fp = (DWORD64 *) context->Fp; /* X[29] */
|
||||
/* mov x29,sp */
|
||||
context->Sp = context->Fp;
|
||||
context->X[29] = fp[0];
|
||||
context->X[30] = fp[1];
|
||||
restore_regs( 29, 2, 0, context, ptrs );
|
||||
}
|
||||
context->Sp += local_size;
|
||||
if (fp_size) restore_fpregs( 8, fp_regs, int_regs, context, ptrs );
|
||||
|
|
Loading…
Add table
Reference in a new issue