-
Notifications
You must be signed in to change notification settings - Fork 18
/
PmipRunner.cs
117 lines (99 loc) · 3.21 KB
/
PmipRunner.cs
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
using System;
using Microsoft.VisualStudio.Debugger;
using Microsoft.VisualStudio.Debugger.CallStack;
using Microsoft.VisualStudio.Debugger.Evaluation;
using Microsoft.VisualStudio.Debugger.Native;
namespace PmipMyCallStack
{
class PmipRunner
{
private static readonly DkmLanguage CppLanguage = DkmLanguage.Create("C++", new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.Cpp));
private readonly DkmStackContext _stackContext;
private readonly DkmStackWalkFrame _frame;
private readonly DkmInspectionContext _inspectionContext;
public PmipRunner(DkmStackContext stackContext, DkmStackWalkFrame frame)
{
_stackContext = stackContext;
_frame = frame;
_inspectionContext = CreateInspectionContext(stackContext, frame);
}
public DkmStackWalkFrame PmipStackFrame()
{
PmipFunctionDataItem pmipFunction;
if (!TryGetPmipFunction(out pmipFunction))
return _frame;
var ip = $"0x{_frame.InstructionAddress.CPUInstructionPart.InstructionPointer:X}";
var call = $"((char*(*)(void*)){pmipFunction.PmipFunction})((void*){ip})";
var result = "";
var isNull = true;
var eval = EvaluateExpression(call, r =>
{
isNull = r.Address.InstructionAddress.CPUInstructionPart.InstructionPointer == 0;
result = r.Value;
});
if (!eval || isNull)
return _frame;
return DkmStackWalkFrame.Create(
_stackContext.Thread,
_frame.InstructionAddress,
_frame.FrameBase,
_frame.FrameSize,
_frame.Flags,
result,
_frame.Registers,
_frame.Annotations);
}
private bool TryGetPmipFunction(out PmipFunctionDataItem pmipFunction)
{
pmipFunction = _stackContext.GetDataItem<PmipFunctionDataItem>();
if (pmipFunction != null)
return true;
foreach (var module in this._frame.RuntimeInstance.GetModuleInstances())
{
var address = (module as DkmNativeModuleInstance)?.FindExportName("mono_pmip", IgnoreDataExports: true);
if (address == null)
continue;
var item = new PmipFunctionDataItem { PmipFunction = "0x" + address.CPUInstructionPart.InstructionPointer.ToString("X") };
pmipFunction = item;
_stackContext.SetDataItem(DkmDataCreationDisposition.CreateAlways, item);
return true;
}
return false;
}
private static DkmLanguageExpression CppExpression(string expression)
{
return DkmLanguageExpression.Create(CppLanguage, DkmEvaluationFlags.None, expression, null);
}
private static DkmInspectionContext CreateInspectionContext(DkmStackContext stackContext, DkmStackWalkFrame frame)
{
return DkmInspectionContext.Create(
stackContext.InspectionSession,
frame.RuntimeInstance,
frame.Thread,
1000,
DkmEvaluationFlags.None,
DkmFuncEvalFlags.None,
10,
CppLanguage,
null);
}
private bool EvaluateExpression(string expression, Action<DkmSuccessEvaluationResult> onSuccess)
{
var workList = DkmWorkList.Create(null);
var success = false;
_inspectionContext.EvaluateExpression(workList, CppExpression(expression), _frame, res =>
{
var resObj = res.ResultObject;
var result = resObj as DkmSuccessEvaluationResult;
if (result != null)
{
success = true;
onSuccess(result);
}
resObj.Close();
});
workList.Execute();
return success;
}
}
}