blob: 9b14d41c836cf45fb649e53d83a05a926987a4df (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
// File: ExcepArm.cpp
#include "common.h"
#include "asmconstants.h"
#include "virtualcallstub.h"
PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispatcherContext)
{
LIMITED_METHOD_DAC_CONTRACT;
UINT_PTR stackSlot = pDispatcherContext->EstablisherFrame + REDIRECTSTUB_SP_OFFSET_CONTEXT;
PTR_PTR_CONTEXT ppContext = dac_cast<PTR_PTR_CONTEXT>((TADDR)stackSlot);
return *ppContext;
}
PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext)
{
LIMITED_METHOD_DAC_CONTRACT;
UINT_PTR stackSlot = pContext->Sp + REDIRECTSTUB_SP_OFFSET_CONTEXT;
PTR_PTR_CONTEXT ppContext = dac_cast<PTR_PTR_CONTEXT>((TADDR)stackSlot);
return *ppContext;
}
#if !defined(DACCESS_COMPILE)
// The next two functions help retrieve data kept relative to FaultingExceptionFrame that is setup
// for handling async exceptions (e.g. AV, NullRef, ThreadAbort, etc).
//
// FEF (and related data) is available relative to R4 - the thing to be kept in mind is that the
// DispatcherContext->ContextRecord:
//
// 1) represents the caller context in the first pass.
// 2) represents the current context in the second pass.
//
// Since R4 is a non-volatile register, this works for us since we setup the value of R4
// in the redirection helpers (e.g. NakedThrowHelper or RedirectForThreadAbort) but do not
// change it in their respective callee functions (e.g. NakedThrowHelper2 or RedirectForThreadAbort2)
// that have the personality routines associated with them (which perform the collided unwind and also
// invoke the two functions below).
//
// Thus, when our personality routine gets called in either passes, DC->ContextRecord->R4 will
// have the same value.
// Returns the pointer to the FEF
FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (T_DISPATCHER_CONTEXT *pDispatcherContext)
{
LIMITED_METHOD_CONTRACT;
return (FaultingExceptionFrame*)((TADDR)pDispatcherContext->ContextRecord->R4);
}
// Returns TRUE if caller should resume execution.
BOOL
AdjustContextForVirtualStub(
EXCEPTION_RECORD *pExceptionRecord,
CONTEXT *pContext)
{
LIMITED_METHOD_CONTRACT;
Thread * pThread = GetThread();
// We may not have a managed thread object. Example is an AV on the helper thread.
// (perhaps during StubManager::IsStub)
if (pThread == NULL)
{
return FALSE;
}
PCODE f_IP = GetIP(pContext);
TADDR pInstr = PCODEToPINSTR(f_IP);
VirtualCallStubManager::StubKind sk;
VirtualCallStubManager::FindStubManager(f_IP, &sk);
if (sk == VirtualCallStubManager::SK_DISPATCH)
{
if (*PTR_WORD(pInstr) != DISPATCH_STUB_FIRST_WORD)
{
_ASSERTE(!"AV in DispatchStub at unknown instruction");
return FALSE;
}
}
else
if (sk == VirtualCallStubManager::SK_RESOLVE)
{
if (*PTR_WORD(pInstr) != RESOLVE_STUB_FIRST_WORD)
{
_ASSERTE(!"AV in ResolveStub at unknown instruction");
return FALSE;
}
}
else
{
return FALSE;
}
PCODE callsite = GetAdjustedCallAddress(GetLR(pContext));
// Lr must already have been saved before calling so it should not be necessary to restore Lr
pExceptionRecord->ExceptionAddress = (PVOID)callsite;
SetIP(pContext, callsite);
return TRUE;
}
#endif // !DACCESS_COMPILE
|