Context record may be stored on stack below context stack. This happens, e. g., with RtlRaiseException().
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/unix/signal_x86_64.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 5334a4d7cc6..264d20de0cd 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1979,17 +1979,21 @@ __ASM_GLOBAL_FUNC( user_exception_dispatcher_trampoline,
void WINAPI do_call_user_exception_dispatcher(EXCEPTION_RECORD *rec, CONTEXT *context, struct stack_layout *stack) { - memcpy(&stack->context, context, sizeof(*context)); + memmove(&stack->context, context, sizeof(*context)); memcpy(&stack->rec, rec, sizeof(*rec));
user_exception_dispatcher_trampoline( stack, pKiUserExceptionDispatcher ); }
__ASM_GLOBAL_FUNC( call_user_exception_dispatcher, - "movq 0x98(%rdx),%rsp\n\t" /* context->Rsp */ - "and $~0xf,%rsp\n\t" - "sub $0x630,%rsp\n\t" /* sizeof(struct stack_layout) */ - "movq %rsp,%r8\n\t" + "movq 0x98(%rdx),%r8\n\t" /* context->Rsp */ + "andq $~0xf,%r8\n\t" + "subq $0x630,%r8\n\t" /* sizeof(struct stack_layout) */ + "cmpq %r8,%rsp\n\t" + "jae done\n\t" + "movq %r8,%rsp\n\t" + + "done:" "jmp " __ASM_NAME("do_call_user_exception_dispatcher") "\n\t")
/***********************************************************************
Paul Gofman pgofman@codeweavers.com writes:
Context record may be stored on stack below context stack. This happens, e. g., with RtlRaiseException().
That doesn't seem right, there may be other things on the stack too. Is there a reason to switch stack to context->Rsp at all?
On 7/2/20 12:09, Alexandre Julliard wrote:
Paul Gofman pgofman@codeweavers.com writes:
Context record may be stored on stack below context stack. This happens, e. g., with RtlRaiseException().
That doesn't seem right, there may be other things on the stack too. Is there a reason to switch stack to context->Rsp at all?
Exception unwinding does not work otherwise, and that matches stack layout on Windows: the context and exception record on stack has a fixed gap after context's Rsp. But it looks we don't need anything else from the stack besides the context, or am I missing something?
Paul Gofman pgofman@codeweavers.com writes:
On 7/2/20 12:09, Alexandre Julliard wrote:
Paul Gofman pgofman@codeweavers.com writes:
Context record may be stored on stack below context stack. This happens, e. g., with RtlRaiseException().
That doesn't seem right, there may be other things on the stack too. Is there a reason to switch stack to context->Rsp at all?
Exception unwinding does not work otherwise, and that matches stack layout on Windows: the context and exception record on stack has a fixed gap after context's Rsp. But it looks we don't need anything else from the stack besides the context, or am I missing something?
Potentially the exception record, if we allow things to be below context->Rsp. Maybe RtlRaiseException is not setting the right Rsp? This could use a few more tests.
On 7/2/20 12:55, Alexandre Julliard wrote:
Paul Gofman pgofman@codeweavers.com writes:
On 7/2/20 12:09, Alexandre Julliard wrote:
Paul Gofman pgofman@codeweavers.com writes:
Context record may be stored on stack below context stack. This happens, e. g., with RtlRaiseException().
That doesn't seem right, there may be other things on the stack too. Is there a reason to switch stack to context->Rsp at all?
Exception unwinding does not work otherwise, and that matches stack layout on Windows: the context and exception record on stack has a fixed gap after context's Rsp. But it looks we don't need anything else from the stack besides the context, or am I missing something?
Potentially the exception record, if we allow things to be below context->Rsp. Maybe RtlRaiseException is not setting the right Rsp? This could use a few more tests.
We could change RtlRaiseException() to set up the stack in a way it is usable for passing to KiUserExceptionDispatcher and thus avoid copying context at all, but this way NtRaiseException() would rely on being called from RtlRaiseException(), while it works other ways too.
What I see from additional tests on Windows is that in KiUserExceptionDispatcher hook the rsp (that is, context pointer) has offset 0x710 from context->Rsp, regardless of how NtRaiseException is called: directly or through RtlRaiseException() with BeingDebugged set to TRUE. The same offset is from fault. So I am not sure how changing RtlRaiseException() can bring that all in line? Maybe I can just save exception record on the current stack before copying context to avoid potential problems?
I guess some part of trickiness here comes from the fact that unlike Windows kernel part we have the same stack in unix part.
As a separate note, I noticed during testing that NtRaiseException() can capture the context itself if the context flags don't have CONTEXT_CONTROL flag (otherwise it uses the given context even if it is completely bogus). But this doesn't seem related here.
On 02/07/2020 11:06, Paul Gofman wrote:
"jae done\n\t"
"movq %r8,%rsp\n\t"
"done:"
Just a small note: you can replace this with:
cmovbq %r8,%rsp