/// <summary> /// Create a DkmEvaluationResult representing a Python object. /// </summary> /// <param name="cppEval">C++ evaluator to use to provide the [C++ view] node for this object.</param> /// <param name="cppTypeName"> /// C++ struct name corresponding to this object type, for use by [C++ view] node. If not specified, it will be inferred from values of /// various function pointers in <c>ob_type</c>, if possible. <c>PyObject</c> is the ultimate fallback. /// </param> public DkmEvaluationResult CreatePyObjectEvaluationResult(DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, string parentName, PythonEvaluationResult pyEvalResult, CppExpressionEvaluator cppEval, string cppTypeName = null, bool hasCppView = false, bool isOwned = false) { var name = pyEvalResult.Name; var valueStore = pyEvalResult.ValueStore as IValueStore<PyObject>; if (valueStore == null) { Debug.Fail("Non-PyObject PythonEvaluationResult passed to CreateEvaluationResult."); throw new ArgumentException(); } var valueObj = valueStore.Read(); string typeName = valueObj.ob_type.Read().tp_name.Read().ReadUnicode(); var reprOptions = new ReprOptions(inspectionContext); string repr = valueObj.Repr(reprOptions); var flags = pyEvalResult.Flags; if (DebuggerOptions.ShowCppViewNodes || valueObj.GetDebugChildren(reprOptions).Any()) { flags |= DkmEvaluationResultFlags.Expandable; } if (!(valueStore is IWritableDataProxy)) { flags |= DkmEvaluationResultFlags.ReadOnly; } if (valueObj is IPyBaseStringObject) { flags |= DkmEvaluationResultFlags.RawString; } var boolObj = valueObj as IPyBoolObject; if (boolObj != null) { flags |= DkmEvaluationResultFlags.Boolean; if (boolObj.ToBoolean()) { flags |= DkmEvaluationResultFlags.BooleanTrue; } } string fullName = name; if (parentName != null) { if (!fullName.StartsWith("[")) { fullName = "." + fullName; } fullName = parentName + fullName; } var pyObjEvalResult = new PyObjectEvaluationResult(stackFrame.Process, fullName, valueStore, cppTypeName, hasCppView, isOwned); return DkmSuccessEvaluationResult.Create( inspectionContext, stackFrame, name, fullName, flags, repr, null, typeName, pyEvalResult.Category, pyEvalResult.AccessType, pyEvalResult.StorageType, pyEvalResult.TypeModifierFlags, null, null, null, pyObjEvalResult); }
private void EvaluateExpressionViaInterpreter(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmLanguageExpression expression, DkmStackWalkFrame stackFrame, DkmCompletionRoutine<DkmEvaluateExpressionAsyncResult> completionRoutine) { var thread = stackFrame.Thread; var process = thread.Process; if (_evalLoopThreadId.Read() != (ulong)thread.SystemPart.Id) { completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create( inspectionContext, stackFrame, expression.Text, expression.Text, "Arbitrary Python expressions can only be evaluated on a thread which is stopped in Python code at a breakpoint or " + "after a step-in or a step-over operation. Only expressions involving global and local variables, object field access, " + "and indexing of built-in collection types with literals can be evaluated in the current context.", DkmEvaluationResultFlags.Invalid, null))); return; } var pythonFrame = PyFrameObject.TryCreate(stackFrame); if (pythonFrame == null) { completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create( inspectionContext, stackFrame, expression.Text, expression.Text, "Could not obtain a Python frame object for the current frame.", DkmEvaluationResultFlags.Invalid, null))); return; } byte[] input = Encoding.UTF8.GetBytes(expression.Text + "\0"); if (input.Length > ExpressionEvaluationBufferSize) { completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create( inspectionContext, stackFrame, expression.Text, expression.Text, "Expression is too long.", DkmEvaluationResultFlags.Invalid, null))); return; } _evalLoopFrame.Write(pythonFrame.Address); process.WriteMemory(_evalLoopInput.Address, input); bool timedOut; using (_evalCompleteEvent = new AutoResetEvent(false)) { thread.BeginFuncEvalExecution(DkmFuncEvalFlags.None); timedOut = !_evalCompleteEvent.WaitOne(ExpressionEvaluationTimeout); _evalCompleteEvent = null; } if (timedOut) { new RemoteComponent.AbortingEvalExecutionRequest().SendLower(process); // We need to stop the process before we can report end of func eval completion using (_evalAbortedEvent = new AutoResetEvent(false)) { process.AsyncBreak(false); if (!_evalAbortedEvent.WaitOne(20000)) { // This is a catastrophic error, since we can't report func eval completion unless we can stop the process, // and VS will hang until we do report completion. At this point we can only kill the debuggee so that the // VS at least gets back to a reasonable state. _evalAbortedEvent = null; process.Terminate(1); completionRoutine(DkmEvaluateExpressionAsyncResult.CreateErrorResult(new Exception("Couldn't abort a failed expression evaluation."))); return; } _evalAbortedEvent = null; } completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create( inspectionContext, stackFrame, expression.Text, expression.Text, "Evaluation timed out.", DkmEvaluationResultFlags.Invalid, null))); return; } ulong objPtr = _evalLoopResult.Read(); var obj = PyObject.FromAddress(process, objPtr); var exc_type = PyObject.FromAddress(process, _evalLoopExcType.Read()); var exc_value = PyObject.FromAddress(process, _evalLoopExcValue.Read()); var exc_str = (PyObject.FromAddress(process, _evalLoopExcStr.Read()) as IPyBaseStringObject).ToStringOrNull(); var sehCode = _evalLoopSEHCode.Read(); if (obj != null) { var cppEval = new CppExpressionEvaluator(inspectionContext, stackFrame); var pyEvalResult = new PythonEvaluationResult(obj, expression.Text) { Flags = DkmEvaluationResultFlags.SideEffect }; var evalResult = CreatePyObjectEvaluationResult(inspectionContext, stackFrame, null, pyEvalResult, cppEval, null, hasCppView: true, isOwned: true); _evalLoopResult.Write(0); // don't let the eval loop decref the object - we will do it ourselves later, when eval result is closed completionRoutine(new DkmEvaluateExpressionAsyncResult(evalResult)); } else if (sehCode != 0) { string errorText = string.Format("Structured exception {0:x08} ", sehCode); if (Enum.IsDefined(typeof(EXCEPTION_CODE), sehCode)) { errorText += "(" + (EXCEPTION_CODE)sehCode + ") "; } errorText += "raised while evaluating expression"; completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create( inspectionContext, stackFrame, expression.Text, expression.Text, errorText, DkmEvaluationResultFlags.Invalid, null))); } else if (exc_type != null) { string typeName; var typeObject = exc_type as PyTypeObject; if (typeObject != null) { typeName = typeObject.tp_name.Read().ReadUnicode(); } else { typeName = "<unknown exception type>"; } completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create( inspectionContext, stackFrame, expression.Text, expression.Text, typeName + " raised while evaluating expression: " + exc_str, DkmEvaluationResultFlags.Invalid, null))); } else { completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create( inspectionContext, stackFrame, expression.Text, expression.Text, "Unknown error occurred while evaluating expression.", DkmEvaluationResultFlags.Invalid, null))); } }
private DkmEvaluationResult GetPythonView(DkmVisualizedExpression visualizedExpression) { var stackFrame = visualizedExpression.StackFrame; var process = stackFrame.Process; var pythonRuntime = process.GetPythonRuntimeInstance(); if (pythonRuntime == null) { return null; } var home = visualizedExpression.ValueHome as DkmPointerValueHome; if (home == null) { Debug.Fail("PythonViewNativeVisualizer given a visualized expression that has a non-DkmPointerValueHome home."); return null; } else if (home.Address == 0) { return null; } var exprEval = process.GetDataItem<ExpressionEvaluator>(); if (exprEval == null) { Debug.Fail("PythonViewNativeVisualizer failed to obtain an instance of ExpressionEvaluator."); return null; } string cppTypeName = null; var childExpr = visualizedExpression as DkmChildVisualizedExpression; if (childExpr != null) { var evalResult = childExpr.EvaluationResult as DkmSuccessEvaluationResult; cppTypeName = evalResult.Type; } else { object punkTypeSymbol; visualizedExpression.GetSymbolInterface(typeof(IDiaSymbol).GUID, out punkTypeSymbol); using (ComPtr.Create(punkTypeSymbol)) { var typeSymbol = punkTypeSymbol as IDiaSymbol; if (typeSymbol != null) { cppTypeName = typeSymbol.name; } } } PyObject objRef; try { objRef = PyObject.FromAddress(process, home.Address); } catch { return null; } var pyEvalResult = new PythonEvaluationResult(objRef, "[Python view]") { Category = DkmEvaluationResultCategory.Property, AccessType = DkmEvaluationResultAccessType.Private }; var inspectionContext = visualizedExpression.InspectionContext; CppExpressionEvaluator cppEval; try { cppEval = new CppExpressionEvaluator(inspectionContext, stackFrame); } catch { return null; } var pythonContext = DkmInspectionContext.Create(visualizedExpression.InspectionSession, pythonRuntime, stackFrame.Thread, inspectionContext.Timeout, inspectionContext.EvaluationFlags, inspectionContext.FuncEvalFlags, inspectionContext.Radix, DkmLanguage.Create("Python", new DkmCompilerId(Guids.MicrosoftVendorGuid, Guids.PythonLanguageGuid)), null); try { return exprEval.CreatePyObjectEvaluationResult(pythonContext, stackFrame, null, pyEvalResult, cppEval, cppTypeName, hasCppView: true); } catch { return null; } }