forked from maraf/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.cpp
More file actions
183 lines (161 loc) · 7.64 KB
/
utils.cpp
File metadata and controls
183 lines (161 loc) · 7.64 KB
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// Type-safe helper wrapper to get an EXCEPTION_RECORD slot as a CORDB_ADDRESS
//
// Arguments:
// pRecord - exception record
// idxSlot - slot to retrieve from.
//
// Returns:
// contents of slot as a CordbAddress.
CORDB_ADDRESS GetExceptionInfoAsAddress(const EXCEPTION_RECORD * pRecord, int idxSlot)
{
_ASSERTE((idxSlot >= 0) && (idxSlot < EXCEPTION_MAXIMUM_PARAMETERS));
// ExceptionInformation is an array of ULONG_PTR. CORDB_ADDRESS is a 0-extended ULONG64.
// So the implicit cast will work here on x86. On 64-bit, it's basically a nop.
return pRecord->ExceptionInformation[idxSlot];
}
// Determine if an exception event is a Debug event for this flavor of the CLR.
//
// Arguments:
// pRecord - exception record
// pClrBaseAddress - clr Instance ID for which CLR in the target we're checking against.
//
// Returns:
// NULL if the exception is not a CLR managed debug event for the given Clr instance.
// Else, address in target process of managed debug event described by the exception (the payload).
//
// Notes:
// This decodes events raised by code:Debugger.SendRawEvent
// Anybody can spoof our exception, so this is not a reliably safe method.
// With multiple CLRs in the same process, it's essential to use the proper pClrBaseAddress.
CORDB_ADDRESS IsEventDebuggerNotification(
const EXCEPTION_RECORD * pRecord,
CORDB_ADDRESS pClrBaseAddress
)
{
_ASSERTE(pRecord != NULL);
// Must specify a CLR instance.
_ASSERTE(pClrBaseAddress != (CORDB_ADDRESS)NULL);
// If it's not even our exception code, then it's not ours.
if (pRecord->ExceptionCode != CLRDBG_NOTIFICATION_EXCEPTION_CODE)
{
return (CORDB_ADDRESS)NULL;
}
//
// Format of an ExceptionInformation parameter is:
// 0: cookie (CLRDBG_EXCEPTION_DATA_CHECKSUM)
// 1: Base address of mscorwks. This identifies the instance of the CLR.
// 2: Target Address of DebuggerIPCEvent, which contains the "real" event.
//
if (pRecord->NumberParameters != 3)
{
return (CORDB_ADDRESS)NULL;
}
// 1st argument should always be the cookie.
// If cookie doesn't match, very likely it's a stray exception that happens to be using
// our code.
DWORD cookie = (DWORD) pRecord->ExceptionInformation[0];
if (cookie != CLRDBG_EXCEPTION_DATA_CHECKSUM)
{
return (CORDB_ADDRESS)NULL;
}
// TODO: We don't do this check in case of non-windows debugging now, because we don't support
// multi-instance debugging.
#if !defined(FEATURE_DBGIPC_TRANSPORT_VM) && !defined(FEATURE_DBGIPC_TRANSPORT_DI)
// If base-address doesn't match, then it's likely an event from another version of the CLR
// in the target.
// We need to be careful here. CORDB_ADDRESS is a ULONG64, whereas ExceptionInformation[1]
// is ULONG_PTR. So on 32-bit, their sizes don't match.
CORDB_ADDRESS pTargetBase = GetExceptionInfoAsAddress(pRecord, 1);
if (pTargetBase != pClrBaseAddress)
{
return (CORDB_ADDRESS)NULL;
}
#endif
// It passes all the format checks. So now get the payload.
CORDB_ADDRESS ptrRemoteManagedEvent = GetExceptionInfoAsAddress(pRecord, 2);
return ptrRemoteManagedEvent;
}
#if defined(FEATURE_DBGIPC_TRANSPORT_VM) || defined(FEATURE_DBGIPC_TRANSPORT_DI)
void InitEventForDebuggerNotification(DEBUG_EVENT * pDebugEvent,
CORDB_ADDRESS pClrBaseAddress,
DebuggerIPCEvent * pIPCEvent)
{
pDebugEvent->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
pDebugEvent->u.Exception.dwFirstChance = TRUE;
pDebugEvent->u.Exception.ExceptionRecord.ExceptionCode = CLRDBG_NOTIFICATION_EXCEPTION_CODE;
pDebugEvent->u.Exception.ExceptionRecord.ExceptionFlags = 0;
pDebugEvent->u.Exception.ExceptionRecord.ExceptionRecord = NULL;
pDebugEvent->u.Exception.ExceptionRecord.ExceptionAddress = 0;
//
// Format of an ExceptionInformation parameter is:
// 0: cookie (CLRDBG_EXCEPTION_DATA_CHECKSUM)
// 1: Base address of mscorwks. This identifies the instance of the CLR.
// 2: Target Address of DebuggerIPCEvent, which contains the "real" event.
//
pDebugEvent->u.Exception.ExceptionRecord.NumberParameters = 3;
pDebugEvent->u.Exception.ExceptionRecord.ExceptionInformation[0] = CLRDBG_EXCEPTION_DATA_CHECKSUM;
pDebugEvent->u.Exception.ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR)CORDB_ADDRESS_TO_PTR(pClrBaseAddress);
pDebugEvent->u.Exception.ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR)pIPCEvent;
_ASSERTE(IsEventDebuggerNotification(&(pDebugEvent->u.Exception.ExceptionRecord), pClrBaseAddress) ==
PTR_TO_CORDB_ADDRESS(pIPCEvent));
}
#endif // defined(FEATURE_DBGIPC_TRANSPORT_VM) || defined(FEATURE_DBGIPC_TRANSPORT_DI)
//-----------------------------------------------------------------------------
// The 'internal' version of our IL to Native map (the DebuggerILToNativeMap struct)
// has an extra field - ICorDebugInfo::SourceTypes source. The 'external/user-visible'
// version (COR_DEBUG_IL_TO_NATIVE_MAP) lacks that field, so we need to translate our
// internal version to the external version.
// "Export" seemed more succinct than "CopyInternalToExternalILToNativeMap" :)
//-----------------------------------------------------------------------------
void ExportILToNativeMap(ULONG32 cMap, // [in] Min size of mapExt, mapInt
COR_DEBUG_IL_TO_NATIVE_MAP mapExt[], // [in] Filled in here
struct DebuggerILToNativeMap mapInt[],// [in] Source of info
SIZE_T sizeOfCode) // [in] Total size of method (bytes)
{
ULONG32 iMap;
_ASSERTE(mapExt != NULL);
_ASSERTE(mapInt != NULL);
for(iMap=0; iMap < cMap; iMap++)
{
mapExt[iMap].ilOffset = mapInt[iMap].ilOffset ;
mapExt[iMap].nativeStartOffset = mapInt[iMap].nativeStartOffset ;
mapExt[iMap].nativeEndOffset = mapInt[iMap].nativeEndOffset ;
// An element that has an end offset of zero, means "till the end of
// the method". Pretty this up so that customers don't have to care about
// this.
if ((DWORD)mapInt[iMap].source & (DWORD)ICorDebugInfo::NATIVE_END_OFFSET_UNKNOWN)
{
mapExt[iMap].nativeEndOffset = (ULONG32)sizeOfCode;
}
#if defined(_DEBUG)
{
// UnsafeGetConfigDWORD
SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE;
static int fReturnSourceTypeForTesting = -1;
if (fReturnSourceTypeForTesting == -1)
fReturnSourceTypeForTesting = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ReturnSourceTypeForTesting);
if (fReturnSourceTypeForTesting)
{
// Steal the most significant four bits from the native end offset for the source type.
_ASSERTE( (mapExt[iMap].nativeEndOffset >> 28) == 0x0 );
_ASSERTE( (ULONG32)(mapInt[iMap].source) < 0xF );
mapExt[iMap].nativeEndOffset |= ((ULONG32)(mapInt[iMap].source) << 28);
}
}
#endif // _DEBUG
}
}
const IPCEventTypeNameMapping DbgIPCEventTypeNames[] =
{
#define IPC_EVENT_TYPE0(type, val) { type, #type },
#define IPC_EVENT_TYPE1(type, val) { type, #type },
#define IPC_EVENT_TYPE2(type, val) { type, #type },
#include "dbgipceventtypes.h"
#undef IPC_EVENT_TYPE2
#undef IPC_EVENT_TYPE1
#undef IPC_EVENT_TYPE0
{ DB_IPCE_INVALID_EVENT, "DB_IPCE_Error" }
};
const size_t nameCount = sizeof(DbgIPCEventTypeNames) / sizeof(DbgIPCEventTypeNames[0]);