public void getset_set(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); string descrVar = useRegisters ? "((PyGetSetDescrObject*)@rcx)" : "descr"; ulong set = cppEval.EvaluateUInt64(descrVar + "->d_getset->set"); _owner.OnPotentialRuntimeExit(thread, set); }
public void PyType_GenericNew(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); string typeVar = useRegisters ? "((PyTypeObject*)@rcx)" : "type"; ulong tp_alloc = cppEval.EvaluateUInt64(typeVar + "->tp_alloc"); _owner.OnPotentialRuntimeExit(thread, tp_alloc); }
public void builtin_next(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); string argsVar = useRegisters ? "((PyTupleObject*)@rdx)" : "((PyTupleObject*)args)"; ulong tp_iternext = cppEval.EvaluateUInt64(argsVar + "->ob_item[0]->ob_type->tp_iternext"); _owner.OnPotentialRuntimeExit(thread, tp_iternext); }
public void PyCFunction_Call(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); ulong ml_meth = cppEval.EvaluateUInt64( "((PyObject*){0})->ob_type == &PyCFunction_Type ? ((PyCFunctionObject*){0})->m_ml->ml_meth : 0", useRegisters ? "@rcx" : "func"); _owner.OnPotentialRuntimeExit(thread, ml_meth); }
public void PyObject_Str(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); string vVar = useRegisters ? "((PyObject*)@rcx)" : "v"; ulong tp_str = cppEval.EvaluateUInt64(vVar + "->ob_type->tp_str"); _owner.OnPotentialRuntimeExit(thread, tp_str); }
public void new_threadstate(DkmThread thread, ulong frameBase, ulong vframe, ulong returnAddress) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); // Addressing this local by name does not work for release builds, so read the return value directly from the register instead. var tstate = PyThreadState.TryCreate(process, cppEval.EvaluateReturnValueUInt64()); if (tstate == null) { return; } _owner.RegisterTracing(tstate); }
public void do_richcompare(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); string vVar = useRegisters ? "((PyObject*)@rcx)" : "v"; string wVar = useRegisters ? "((PyObject*)@rdx)" : "w"; ulong tp_richcompare1 = cppEval.EvaluateUInt64(vVar + "->ob_type->tp_richcompare"); _owner.OnPotentialRuntimeExit(thread, tp_richcompare1); ulong tp_richcompare2 = cppEval.EvaluateUInt64(wVar + "->ob_type->tp_richcompare"); _owner.OnPotentialRuntimeExit(thread, tp_richcompare2); }
public void PyInterpreterState_New(DkmThread thread, ulong frameBase, ulong vframe, ulong returnAddress) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); var istate = PyInterpreterState.TryCreate(process, cppEval.EvaluateReturnValueUInt64()); if (istate == null) { return; } if (process.GetPythonRuntimeInfo().LanguageVersion >= PythonLanguageVersion.V36) { _owner.RegisterJITTracing(istate); } }
public void call_function(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); int oparg = cppEval.EvaluateInt32(useRegisters ? "@rdx" : "oparg"); int na = oparg & 0xff; int nk = (oparg >> 8) & 0xff; int n = na + 2 * nk; ulong func = cppEval.EvaluateUInt64( "*((*(PyObject***){0}) - {1} - 1)", useRegisters ? "@rcx" : "pp_stack", n); var obj = PyObject.FromAddress(process, func); ulong ml_meth = cppEval.EvaluateUInt64( "((PyObject*){0})->ob_type == &PyCFunction_Type ? ((PyCFunctionObject*){0})->m_ml->ml_meth : 0", func); _owner.OnPotentialRuntimeExit(thread, ml_meth); }
public static void PyCode_NewEmpty(DkmThread thread, ulong frameBase, ulong vframe, ulong returnAddress) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); ulong filenamePtr = cppEval.EvaluateUInt64("filename"); if (filenamePtr == 0) { return; } string filename = new CStringProxy(process, filenamePtr).ReadUnicode(); if (process.GetPythonRuntimeInstance().GetModuleInstances().Any(mi => mi.FullName == filename)) { return; } new RemoteComponent.CreateModuleRequest { ModuleId = Guid.NewGuid(), FileName = filename }.SendLower(process); }
/// <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); }
public void GetFrameLocals(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame stackFrame, DkmCompletionRoutine<DkmGetFrameLocalsAsyncResult> completionRoutine) { var pythonFrame = PyFrameObject.TryCreate(stackFrame); if (pythonFrame == null) { Debug.Fail("Non-Python frame passed to GetFrameLocals."); throw new NotSupportedException(); } var cppEval = new CppExpressionEvaluator(inspectionContext, stackFrame); var evalResults = new List<DkmEvaluationResult>(); var f_code = pythonFrame.f_code.Read(); var f_localsplus = pythonFrame.f_localsplus; // Process cellvars and freevars first, because function arguments can appear in both cellvars and varnames if the argument is captured by a closure, // in which case we want to use the cellvar because the regular var slot will then be unused by Python (and in Python 3.4+, nulled out). var namesSeen = new HashSet<string>(); var cellNames = f_code.co_cellvars.Read().ReadElements().Concat(f_code.co_freevars.Read().ReadElements()); var cellSlots = f_localsplus.Skip(f_code.co_nlocals.Read()); foreach (var pair in cellNames.Zip(cellSlots, (nameObj, cellSlot) => new { nameObj, cellSlot = cellSlot })) { var nameObj = pair.nameObj; var cellSlot = pair.cellSlot; var name = (nameObj.Read() as IPyBaseStringObject).ToStringOrNull(); if (name == null) { continue; } namesSeen.Add(name); if (cellSlot.IsNull) { continue; } var cell = cellSlot.Read() as PyCellObject; if (cell == null) { continue; } var localPtr = cell.ob_ref; if (localPtr.IsNull) { continue; } var evalResult = CreatePyObjectEvaluationResult(inspectionContext, stackFrame, null, new PythonEvaluationResult(localPtr, name), cppEval); evalResults.Add(evalResult); } PyTupleObject co_varnames = f_code.co_varnames.Read(); foreach (var pair in co_varnames.ReadElements().Zip(f_localsplus, (nameObj, varSlot) => new { nameObj, cellSlot = varSlot })) { var nameObj = pair.nameObj; var varSlot = pair.cellSlot; var name = (nameObj.Read() as IPyBaseStringObject).ToStringOrNull(); if (name == null) { continue; } // Check for function argument that was promoted to a cell. if (!namesSeen.Add(name)) { continue; } if (varSlot.IsNull) { continue; } var evalResult = CreatePyObjectEvaluationResult(inspectionContext, stackFrame, null, new PythonEvaluationResult(varSlot, name), cppEval); evalResults.Add(evalResult); } var globals = pythonFrame.f_globals.TryRead(); if (globals != null) { var globalsEvalResult = new GlobalsEvaluationResult { Globals = globals }; DkmEvaluationResult evalResult = DkmSuccessEvaluationResult.Create( inspectionContext, stackFrame, "[Globals]", null, DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable, null, null, null, DkmEvaluationResultCategory.Property, DkmEvaluationResultAccessType.None, DkmEvaluationResultStorageType.None, DkmEvaluationResultTypeModifierFlags.None, null, null, null, globalsEvalResult); // If it is a top-level module frame, show globals inline; otherwise, show them under the [Globals] node. if (f_code.co_name.Read().ToStringOrNull() == "<module>") { evalResults.AddRange(globalsEvalResult.GetChildren(this, evalResult, inspectionContext)); } else { evalResults.Add(evalResult); // Show any globals that are directly referenced by the function inline even in local frames. var globalVars = (from pair in globals.ReadElements() let nameObj = pair.Key as IPyBaseStringObject where nameObj != null select new { Name = nameObj.ToString(), Value = pair.Value } ).ToLookup(v => v.Name, v => v.Value); PyTupleObject co_names = f_code.co_names.Read(); foreach (var nameObj in co_names.ReadElements()) { var name = (nameObj.Read() as IPyBaseStringObject).ToStringOrNull(); if (name == null) { continue; } // If this is a used name but it was not in varnames or freevars, it is a directly referenced global. if (!namesSeen.Add(name)) { continue; } var varSlot = globalVars[name].FirstOrDefault(); if (varSlot.Process != null) { evalResult = CreatePyObjectEvaluationResult(inspectionContext, stackFrame, null, new PythonEvaluationResult(varSlot, name), cppEval); evalResults.Add(evalResult); } } } } var enumContext = DkmEvaluationResultEnumContext.Create(evalResults.Count, stackFrame, inspectionContext, new EvaluationResults { Results = evalResults.OrderBy(er => er.Name) }); completionRoutine(new DkmGetFrameLocalsAsyncResult(enumContext)); }
public List<DkmEvaluationResult> GetChildren(ExpressionEvaluator exprEval, DkmEvaluationResult result, DkmInspectionContext inspectionContext) { var stackFrame = result.StackFrame; var cppEval = new CppExpressionEvaluator(inspectionContext, stackFrame); var obj = ValueStore.Read(); var evalResults = new List<DkmEvaluationResult>(); var reprOptions = new ReprOptions(inspectionContext); var reprBuilder = new ReprBuilder(reprOptions); if (DebuggerOptions.ShowCppViewNodes && !HasCppView) { if (CppTypeName == null) { // Try to guess the object's C++ type by looking at function pointers in its PyTypeObject. If they are pointing // into a module for which symbols are available, C++ EE should be able to resolve them into something like // "0x1e120d50 {python33_d.dll!list_dealloc(PyListObject *)}". If we are lucky, one of those functions will have // the first argument declared as a strongly typed pointer, rather than PyObject* or void*. CppTypeName = "PyObject"; CppTypeModuleName = null; foreach (string methodField in _methodFields) { var funcPtrEvalResult = cppEval.TryEvaluateObject(null, "PyObject", obj.Address, ".ob_type->" + methodField) as DkmSuccessEvaluationResult; if (funcPtrEvalResult == null || funcPtrEvalResult.Value.IndexOf('{') < 0) { continue; } var match = _cppFirstArgTypeFromFuncPtrRegex.Match(funcPtrEvalResult.Value); string module = match.Groups["module"].Value; string firstArgType = match.Groups["type"].Value; if (firstArgType != "void" && firstArgType != "PyObject" && firstArgType != "_object") { CppTypeName = firstArgType; CppTypeModuleName = module; break; } } } string cppExpr = CppExpressionEvaluator.GetExpressionForObject(CppTypeModuleName, CppTypeName, obj.Address, ",!"); var evalResult = DkmIntermediateEvaluationResult.Create( inspectionContext, stackFrame, "[C++ view]", "{C++}" + cppExpr, cppExpr, CppExpressionEvaluator.CppLanguage, stackFrame.Process.GetNativeRuntimeInstance(), null); evalResults.Add(evalResult); } int i = 0; foreach (var child in obj.GetDebugChildren(reprOptions).Take(MaxDebugChildren)) { if (child.Name == null) { reprBuilder.Clear(); reprBuilder.AppendFormat("[{0:PY}]", i++); child.Name = reprBuilder.ToString(); } DkmEvaluationResult evalResult; if (child.ValueStore is IValueStore<PyObject>) { evalResult = exprEval.CreatePyObjectEvaluationResult(inspectionContext, stackFrame, FullName, child, cppEval); } else { var value = child.ValueStore.Read(); reprBuilder.Clear(); reprBuilder.AppendLiteral(value); string type = null; if (Process.GetPythonRuntimeInfo().LanguageVersion <= PythonLanguageVersion.V27) { _typeMapping2x.TryGetValue(value.GetType(), out type); } if (type == null) { _typeMapping.TryGetValue(value.GetType(), out type); } var flags = DkmEvaluationResultFlags.ReadOnly; if (value is string) { flags |= DkmEvaluationResultFlags.RawString; } string childFullName = child.Name; if (FullName != null) { if (childFullName.EndsWith("()")) { // len() childFullName = childFullName.Substring(0, childFullName.Length - 2) + "(" + FullName + ")"; } else { if (!childFullName.StartsWith("[")) { // [0], ['fob'] etc childFullName = "." + childFullName; } childFullName = FullName + childFullName; } } evalResult = DkmSuccessEvaluationResult.Create( inspectionContext, stackFrame, child.Name, childFullName, flags, reprBuilder.ToString(), null, type, child.Category, child.AccessType, child.StorageType, child.TypeModifierFlags, null, null, null, new RawEvaluationResult { Value = value }); } evalResults.Add(evalResult); } return evalResults; }
public List<DkmEvaluationResult> GetChildren(ExpressionEvaluator exprEval, DkmEvaluationResult result, DkmInspectionContext inspectionContext) { var stackFrame = result.StackFrame; var cppEval = new CppExpressionEvaluator(inspectionContext, stackFrame); var evalResults = new List<DkmEvaluationResult>(); foreach (var pair in Globals.ReadElements()) { var name = pair.Key as IPyBaseStringObject; if (name == null) { continue; } var evalResult = exprEval.CreatePyObjectEvaluationResult(inspectionContext, stackFrame, null, new PythonEvaluationResult(pair.Value, name.ToString()), cppEval); evalResults.Add(evalResult); } return evalResults.OrderBy(er => er.Name).ToList(); }
// This step-in gate is not marked [StepInGate] because it doesn't live in pythonXX.dll, and so we register it manually. public void _call_function_pointer(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) { var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); ulong pProc = cppEval.EvaluateUInt64(useRegisters ? "@rdx" : "pProc"); _owner.OnPotentialRuntimeExit(thread, pProc); }
public void PyObject_Call(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); string funcVar = useRegisters ? "((PyObject*)@rcx)" : "func"; ulong tp_call = cppEval.EvaluateUInt64(funcVar + "->ob_type->tp_call"); _owner.OnPotentialRuntimeExit(thread, tp_call); }
public static void PyCode_New(DkmThread thread, ulong frameBase, ulong vframe, ulong returnAddress) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); var filenamePtr = cppEval.EvaluateUInt64("filename"); var filenameObj = PyObject.FromAddress(process, filenamePtr) as IPyBaseStringObject; if (filenameObj == null) { return; } string filename = filenameObj.ToString(); if (process.GetPythonRuntimeInstance().GetModuleInstances().Any(mi => mi.FullName == filename)) { return; } new RemoteComponent.CreateModuleRequest { ModuleId = Guid.NewGuid(), FileName = filename }.SendLower(process); }
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; } }
public void PyObject_SetAttr(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); string vVar = useRegisters ? "((PyObject*)@rcx)" : "v"; ulong tp_setattr = cppEval.EvaluateUInt64(vVar + "->ob_type->tp_setattr"); _owner.OnPotentialRuntimeExit(thread, tp_setattr); ulong tp_setattro = cppEval.EvaluateUInt64(vVar + "->ob_type->tp_setattro"); _owner.OnPotentialRuntimeExit(thread, tp_setattro); }
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); } // TODO: Localization - [Python view] also appears in .natvis file, leave as-is for now 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); } }
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))); } }
public void PyIter_Next(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); string iterVar = useRegisters ? "((PyObject*)@rcx)" : "iter"; ulong tp_iternext = cppEval.EvaluateUInt64(iterVar + "->ob_type->tp_iternext"); _owner.OnPotentialRuntimeExit(thread, tp_iternext); }
public void new_threadstate(DkmThread thread, ulong frameBase, ulong vframe) { var process = thread.Process; var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe); // Addressing this local by name does not work for release builds, so read the return value directly from the register instead. var tstate = new PyThreadState(thread.Process, cppEval.EvaluateReturnValueUInt64()); if (tstate == null) { return; } _owner.RegisterTracing(tstate); }