1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5#include "pal/dbgmsg.h"
6SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do this first
7
8#include "pal/palinternal.h"
9#include "pal/context.h"
10#include "pal/signal.hpp"
11#include "pal/utils.h"
12#include <sys/ucontext.h>
13
14/*++
15Function :
16 signal_handler_worker
17
18 Handles signal on the original stack where the signal occured.
19 Invoked via setcontext.
20
21Parameters :
22 POSIX signal handler parameter list ("man sigaction" for details)
23 returnPoint - context to which the function returns if the common_signal_handler returns
24
25 (no return value)
26--*/
27void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint)
28{
29 ucontext_t *ucontext = (ucontext_t *)context;
30 size_t faultSp = (size_t)MCREG_Rsp(ucontext->uc_mcontext);
31
32 _ASSERTE(IS_ALIGNED(faultSp, 8));
33
34 size_t fakeFrameReturnAddress;
35
36 if (IS_ALIGNED(faultSp, 16))
37 {
38 fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset0 + (size_t)CallSignalHandlerWrapper0;
39 }
40 else
41 {
42 fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset8 + (size_t)CallSignalHandlerWrapper8;
43 }
44
45 // preserve 128 bytes long red zone and align stack pointer
46 size_t* sp = (size_t*)ALIGN_DOWN(faultSp - 128, 16);
47
48 // Build fake stack frame to enable the stack unwinder to unwind from signal_handler_worker to the faulting instruction
49 *--sp = (size_t)MCREG_Rip(ucontext->uc_mcontext);
50 *--sp = (size_t)MCREG_Rbp(ucontext->uc_mcontext);
51 size_t fp = (size_t)sp;
52 *--sp = fakeFrameReturnAddress;
53
54 // Switch the current context to the signal_handler_worker and the original stack
55 CONTEXT context2;
56 RtlCaptureContext(&context2);
57
58 // We don't care about the other registers state since the stack unwinding restores
59 // them for the target frame directly from the signal context.
60 context2.Rsp = (size_t)sp;
61 context2.Rbx = (size_t)faultSp;
62 context2.Rbp = (size_t)fp;
63 context2.Rip = (size_t)signal_handler_worker;
64 context2.Rdi = code;
65 context2.Rsi = (size_t)siginfo;
66 context2.Rdx = (size_t)context;
67 context2.Rcx = (size_t)returnPoint;
68
69 RtlRestoreContext(&context2, NULL);
70}
71