public static void VscxOnModuleInstanceLoad(this DkmProcess process, DkmModuleInstance module, DkmWorkList workList) { AutoAttachToChildHandler handler = process.GetDataItem<AutoAttachToChildHandler>(); if (handler == null || module.TagValue != DkmModuleInstance.Tag.NativeModuleInstance) return; handler.OnModuleInstanceLoad((DkmNativeModuleInstance)module, workList); }
void IDkmClrResultProvider.GetResult(DkmClrValue value, DkmWorkList workList, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmInspectionContext inspectionContext, ReadOnlyCollection<string> formatSpecifiers, string resultName, string resultFullName, DkmCompletionRoutine<DkmEvaluationAsyncResult> completionRoutine) { if (formatSpecifiers == null) { formatSpecifiers = Formatter.NoFormatSpecifiers; } if (resultFullName != null) { ReadOnlyCollection<string> otherSpecifiers; resultFullName = FullNameProvider.GetClrExpressionAndFormatSpecifiers(inspectionContext, resultFullName, out otherSpecifiers); foreach (var formatSpecifier in otherSpecifiers) { formatSpecifiers = Formatter.AddFormatSpecifier(formatSpecifiers, formatSpecifier); } } var wl = new WorkList(workList, e => completionRoutine(DkmEvaluationAsyncResult.CreateErrorResult(e))); wl.ContinueWith( () => GetRootResultAndContinue( value, wl, declaredType, declaredTypeInfo, inspectionContext, resultName, resultFullName, formatSpecifiers, result => wl.ContinueWith(() => completionRoutine(new DkmEvaluationAsyncResult(result))))); }
/// <summary> /// This method is called by the debug engine to get the text representation of the return /// value of a stack frame. /// </summary> /// <param name="inspectionContext">Context of the evaluation. This contains options/flags /// to be used during compilation. It also contains the InspectionSession. The inspection /// session is the object that provides lifetime management for our objects. When the user /// steps or continues the process, the debug engine will dispose of the inspection session</param> /// <param name="workList">The current work list. This is used to batch asynchronous /// work items. If any asynchronous calls are needed later, this is the work list to pass /// to the asynchronous call. It's not needed in our case.</param> /// <param name="frame">The frame to get the text representation of the return value for</param> /// <param name="completionRoutine">Completion routine to call when work is completed</param> void IDkmLanguageFrameDecoder.GetFrameReturnType( DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmCompletionRoutine<DkmGetFrameReturnTypeAsyncResult> completionRoutine) { string name = TryGetFrameReturnTypeHelper(inspectionContext, frame) ?? "<Unknown>"; completionRoutine(new DkmGetFrameReturnTypeAsyncResult(name)); }
/// <summary> /// This method is called by the debug engine to get the text representation of a stack /// frame. /// </summary> /// <param name="inspectionContext">Context of the evaluation. This contains options/flags /// to be used during compilation. It also contains the InspectionSession. The inspection /// session is the object that provides lifetime management for our objects. When the user /// steps or continues the process, the debug engine will dispose of the inspection session</param> /// <param name="workList">The current work list. This is used to batch asynchronous /// work items. If any asynchronous calls are needed later, this is the work list to pass /// to the asynchronous call. It's not needed in our case.</param> /// <param name="frame">The frame to get the text representation for</param> /// <param name="argumentFlags">Option flags to change the way we format frames</param> /// <param name="completionRoutine">Completion routine to call when work is completed</param> void IDkmLanguageFrameDecoder.GetFrameName( DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmVariableInfoFlags argumentFlags, DkmCompletionRoutine<DkmGetFrameNameAsyncResult> completionRoutine) { string name = TryGetFrameNameHelper(inspectionContext, frame, argumentFlags) ?? "<Unknown Method>"; completionRoutine(new DkmGetFrameNameAsyncResult(name)); }
void IDkmClrResultProvider.GetChildren(DkmEvaluationResult evaluationResult, DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmGetChildrenAsyncResult> completionRoutine) { var dataItem = evaluationResult.GetDataItem<EvalResultDataItem>(); if (dataItem == null) { // We don't know about this result. Call next implementation evaluationResult.GetChildren(workList, initialRequestSize, inspectionContext, completionRoutine); return; } completionRoutine(GetChildren(inspectionContext, evaluationResult, dataItem, initialRequestSize)); }
void IDkmClrResultProvider.GetResult(DkmClrValue value, DkmWorkList workList, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmInspectionContext inspectionContext, ReadOnlyCollection<string> formatSpecifiers, string resultName, string resultFullName, DkmCompletionRoutine<DkmEvaluationAsyncResult> completionRoutine) { // TODO: Use full name var wl = new WorkList(workList, e => completionRoutine(DkmEvaluationAsyncResult.CreateErrorResult(e))); GetRootResultAndContinue( value, wl, declaredType, declaredTypeInfo, inspectionContext, resultName, result => wl.ContinueWith(() => completionRoutine(new DkmEvaluationAsyncResult(result)))); wl.Execute(); }
public void OnModuleInstanceLoad(DkmNativeModuleInstance module, DkmWorkList workList) { bool isKernel32 = module.Name.Equals( "Kernel32.dll", StringComparison.CurrentCultureIgnoreCase); bool isAdvapi32 = module.Name.Equals( "Advapi32.dll", StringComparison.CurrentCultureIgnoreCase); // For historical reasons, Kernel32.dll contains CreateProcess and Advapi32.dll contains // CreateProcessAsUser. if (isKernel32) { HookCreateProcess(module, "CreateProcessW", CreateFrameAnalyzer(module, _createProcessParams)); } else if (isAdvapi32) { HookCreateProcess(module, "CreateProcessAsUserW", CreateFrameAnalyzer(module, _createProcessAsUserParams)); } }
public void GetChildren(DkmEvaluationResult result, DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmGetChildrenAsyncResult> completionRoutine) { var asyncEvalResult = result.GetDataItem<CppViewEvaluationResult>(); if (asyncEvalResult != null) { asyncEvalResult.GetChildren(result, workList, initialRequestSize, inspectionContext, completionRoutine); return; } var pyEvalResult = (IPythonEvaluationResult)result.GetDataItem<PyObjectEvaluationResult>() ?? (IPythonEvaluationResult)result.GetDataItem<GlobalsEvaluationResult>(); if (pyEvalResult != null) { var childResults = pyEvalResult.GetChildren(this, result, inspectionContext); completionRoutine( new DkmGetChildrenAsyncResult( new DkmEvaluationResult[0], DkmEvaluationResultEnumContext.Create( childResults.Count, result.StackFrame, inspectionContext, new EvaluationResults { Results = childResults.ToArray() }))); return; } Debug.Fail("GetChildren called on an unsupported DkmEvaluationResult."); throw new NotSupportedException(); }
public void GetItems(DkmEvaluationResultEnumContext enumContext, DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine<DkmEvaluationEnumAsyncResult> completionRoutine) { var evalResults = enumContext.GetDataItem<EvaluationResults>(); if (evalResults == null) { Debug.Fail("GetItems called on a DkmEvaluationResultEnumContext without an associated EvaluationResults."); throw new NotSupportedException(); } var result = evalResults.Results.Skip(startIndex).Take(count).ToArray(); completionRoutine(new DkmEvaluationEnumAsyncResult(result)); }
public void GetChildren(DkmEvaluationResult result, DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmGetChildrenAsyncResult> completionRoutine) { CppEvaluationResult.GetChildren(workList, initialRequestSize, CppEvaluationResult.InspectionContext, (cppResult) => { completionRoutine(cppResult); }); }
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)); }
void IDkmClrResultProvider.GetChildren(DkmEvaluationResult evaluationResult, DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmGetChildrenAsyncResult> completionRoutine) { evaluationResult.GetChildren(workList, initialRequestSize, inspectionContext, completionRoutine); }
private static void EvaluateDebuggerDisplayStringAndContinue( DkmClrValue value, DkmWorkList workList, DkmInspectionContext inspectionContext, DkmClrType targetType, string str, CompletionRoutine<DkmEvaluateDebuggerDisplayStringAsyncResult> onCompleted, CompletionRoutine<Exception> onException) { DkmCompletionRoutine<DkmEvaluateDebuggerDisplayStringAsyncResult> completionRoutine = result => { try { onCompleted(result); } catch (Exception e) { onException(e); } }; if (str == null) { completionRoutine(default(DkmEvaluateDebuggerDisplayStringAsyncResult)); } else { value.EvaluateDebuggerDisplayString(workList, inspectionContext, targetType, str, completionRoutine); } }
internal WorkList(DkmWorkList workList, CompletionRoutine<Exception> onException) { InnerWorkList = workList; _onException = onException; }
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))); } }
void IDkmClrResultProvider.GetItems(DkmEvaluationResultEnumContext enumContext, DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine<DkmEvaluationEnumAsyncResult> completionRoutine) { try { var dataItem = enumContext.GetDataItem<EnumContextDataItem>(); if (dataItem == null) { // We don't know about this result. Call next implementation enumContext.GetItems(workList, startIndex, count, completionRoutine); return; } completionRoutine(GetItems(enumContext.InspectionContext, dataItem.EvalResultDataItem, startIndex, count)); } catch (Exception e) when (ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
private void GetChildrenAndContinue(EvalResultDataItem dataItem, DkmWorkList workList, DkmStackWalkFrame stackFrame, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmGetChildrenAsyncResult> completionRoutine) { var expansion = dataItem.Expansion; var rows = ArrayBuilder<EvalResultDataItem>.GetInstance(); int index = 0; if (expansion != null) { expansion.GetRows(this, rows, inspectionContext, dataItem, dataItem.Value, 0, initialRequestSize, visitAll: true, index: ref index); } var numRows = rows.Count; Debug.Assert(index >= numRows); Debug.Assert(initialRequestSize >= numRows); var initialChildren = new DkmEvaluationResult[numRows]; var wl = new WorkList(workList, e => completionRoutine(DkmGetChildrenAsyncResult.CreateErrorResult(e))); GetEvaluationResultsAndContinue(rows, initialChildren, 0, numRows, wl, inspectionContext, stackFrame, () => wl.ContinueWith( () => { var enumContext = DkmEvaluationResultEnumContext.Create(index, stackFrame, inspectionContext, new EnumContextDataItem(dataItem)); completionRoutine(new DkmGetChildrenAsyncResult(initialChildren, enumContext)); rows.Free(); })); wl.Execute(); }
public void GetFrameName(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmVariableInfoFlags argumentFlags, DkmCompletionRoutine<DkmGetFrameNameAsyncResult> completionRoutine) { var insAddr = frame.InstructionAddress as DkmCustomInstructionAddress; if (insAddr == null) { Debug.Fail("GetFrameName called on a Python frame without a proper instruction address."); throw new InvalidOperationException(); } var loc = new SourceLocation(insAddr.AdditionalData, frame.Process); completionRoutine(new DkmGetFrameNameAsyncResult(loc.FunctionName)); }
void IDkmClrResultProvider.GetResult(DkmClrValue clrValue, DkmWorkList workList, DkmClrType declaredType, DkmClrCustomTypeInfo customTypeInfo, DkmInspectionContext inspectionContext, ReadOnlyCollection<string> formatSpecifiers, string resultName, string resultFullName, DkmCompletionRoutine<DkmEvaluationAsyncResult> completionRoutine) { clrValue.GetResult( workList, declaredType, customTypeInfo, inspectionContext, formatSpecifiers, resultName, resultFullName, result => { var type = declaredType.GetLmrType(); if (type.IsPointer) { var r = (DkmSuccessEvaluationResult)result.Result; // TODO: Why aren't modopts for & properties included? r.GetChildren( workList, 1, inspectionContext, children => { var c = (DkmSuccessEvaluationResult)children.InitialChildren[0]; r = DkmSuccessEvaluationResult.Create( c.InspectionContext, c.StackFrame, r.Name, r.FullName, c.Flags, c.Value, r.EditableValue, r.Type, r.Category, r.Access, r.StorageType, r.TypeModifierFlags, null, r.CustomUIVisualizers, null, null); completionRoutine(new DkmEvaluationAsyncResult(r)); }); } else { completionRoutine(result); } }); }
void IDkmClrResultProvider.GetItems(DkmEvaluationResultEnumContext enumContext, DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine<DkmEvaluationEnumAsyncResult> completionRoutine) { enumContext.GetItems(workList, startIndex, count, completionRoutine); }
public void EvaluateExpression(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmLanguageExpression expression, DkmStackWalkFrame stackFrame, DkmCompletionRoutine<DkmEvaluateExpressionAsyncResult> completionRoutine) { var name = expression.Text; GetFrameLocals(inspectionContext, workList, stackFrame, getFrameLocalsResult => { getFrameLocalsResult.EnumContext.GetItems(workList, 0, int.MaxValue, localGetItemsResult => { var vars = localGetItemsResult.Items.OfType<DkmSuccessEvaluationResult>(); var globals = vars.FirstOrDefault(er => er.Name == "[Globals]"); if (globals == null) { if (!EvaluateExpressionByWalkingObjects(vars, inspectionContext, workList, expression, stackFrame, completionRoutine)) { EvaluateExpressionViaInterpreter(inspectionContext, workList, expression, stackFrame, completionRoutine); } } else { globals.GetChildren(workList, 0, inspectionContext, globalsGetChildrenResult => { globalsGetChildrenResult.EnumContext.GetItems(workList, 0, int.MaxValue, globalsGetItemsResult => { vars = vars.Concat(globalsGetItemsResult.Items.OfType<DkmSuccessEvaluationResult>()); if (!EvaluateExpressionByWalkingObjects(vars, inspectionContext, workList, expression, stackFrame, completionRoutine)) { EvaluateExpressionViaInterpreter(inspectionContext, workList, expression, stackFrame, completionRoutine); } }); }); } }); }); }
void IDkmClrResultProvider.GetItems(DkmEvaluationResultEnumContext enumContext, DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine<DkmEvaluationEnumAsyncResult> completionRoutine) { var enumContextDataItem = enumContext.GetDataItem<EnumContextDataItem>(); if (enumContextDataItem == null) { // We don't know about this result. Call next implementation enumContext.GetItems(workList, startIndex, count, completionRoutine); return; } var evaluationResult = enumContextDataItem.Result; var dataItem = evaluationResult.GetDataItem<EvalResultDataItem>(); var expansion = dataItem.Expansion; if (expansion == null) { completionRoutine(new DkmEvaluationEnumAsyncResult(new DkmEvaluationResult[0])); return; } var inspectionContext = enumContext.InspectionContext; var rows = ArrayBuilder<EvalResult>.GetInstance(); int index = 0; expansion.GetRows(this, rows, inspectionContext, dataItem, dataItem.Value, startIndex, count, visitAll: false, index: ref index); var numRows = rows.Count; Debug.Assert(count >= numRows); var results = new DkmEvaluationResult[numRows]; CompletionRoutine<Exception> onException = e => completionRoutine(DkmEvaluationEnumAsyncResult.CreateErrorResult(e)); var wl = new WorkList(workList, onException); wl.ContinueWith(() => GetEvaluationResultsAndContinue(evaluationResult, rows, results, 0, numRows, wl, inspectionContext, () => wl.ContinueWith( () => { completionRoutine(new DkmEvaluationEnumAsyncResult(results)); rows.Free(); }), onException)); }
/// <summary> /// Tries to evaluate the given expression by treating it as a chain of member access and indexing operations (e.g. <c>fob[0].oar.baz['abc'].blah</c>), /// and looking up the corresponding members in data model provided by <see cref="GetFrameLocals"/>. /// </summary> /// <param name="vars">List of variables, in the context of which the expression is evaluated.</param> /// <returns> /// <c>true</c> if evaluation was successful, or if it failed and no fallback is possible (e.g. expression is invalid). /// <c>false</c> if evaluation was not successful due to the limitations of this evaluator, and it may be possible to evaluate it correctly by other means. /// </returns> private bool EvaluateExpressionByWalkingObjects(IEnumerable<DkmSuccessEvaluationResult> vars, DkmInspectionContext inspectionContext, DkmWorkList workList, DkmLanguageExpression expression, DkmStackWalkFrame stackFrame, DkmCompletionRoutine<DkmEvaluateExpressionAsyncResult> completionRoutine) { var pyrtInfo = stackFrame.Thread.Process.GetPythonRuntimeInfo(); var parserOptions = new ParserOptions { ErrorSink = new StringErrorSink() }; var parser = Parser.CreateParser(new StringReader(expression.Text), pyrtInfo.LanguageVersion, parserOptions); var expr = ((ReturnStatement)parser.ParseTopExpression().Body).Expression; string errorText = parserOptions.ErrorSink.ToString(); if (!string.IsNullOrEmpty(errorText)) { completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create( inspectionContext, stackFrame, expression.Text, expression.Text, errorText, DkmEvaluationResultFlags.Invalid, null))); return true; } // Unroll the AST into a sequence of member access and indexing operations, if possible. var path = new Stack<string>(); var reprBuilder = new ReprBuilder(new ReprOptions(stackFrame.Thread.Process)); while (true) { var memberExpr = expr as MemberExpression; if (memberExpr != null) { path.Push(memberExpr.Name); expr = memberExpr.Target; continue; } var indexingExpr = expr as IndexExpression; if (indexingExpr != null) { var indexExpr = indexingExpr.Index as ConstantExpression; if (indexExpr != null) { reprBuilder.Clear(); reprBuilder.AppendFormat("[{0:PY}]", indexExpr.Value); path.Push(reprBuilder.ToString()); expr = indexingExpr.Target; continue; } } break; } var varExpr = expr as NameExpression; if (varExpr == null) { return false; } path.Push(varExpr.Name); // Walk the path through Locals while (true) { var name = path.Pop(); var evalResult = vars.FirstOrDefault(er => er.Name == name); if (evalResult == null) { return false; } if (path.Count == 0) { // Clone the evaluation result, but use expression text as its name. DkmDataItem dataItem = (DkmDataItem)evalResult.GetDataItem<PyObjectEvaluationResult>() ?? (DkmDataItem)evalResult.GetDataItem<GlobalsEvaluationResult>() ?? (DkmDataItem)evalResult.GetDataItem<CppViewEvaluationResult>() ?? (DkmDataItem)evalResult.GetDataItem<RawEvaluationResult>(); evalResult = DkmSuccessEvaluationResult.Create( evalResult.InspectionContext, evalResult.StackFrame, expression.Text, expression.Text, evalResult.Flags, evalResult.Value, evalResult.EditableValue, evalResult.Type, evalResult.Category, evalResult.Access, evalResult.StorageType, evalResult.TypeModifierFlags, evalResult.Address, evalResult.CustomUIVisualizers, evalResult.ExternalModules, dataItem); completionRoutine(new DkmEvaluateExpressionAsyncResult(evalResult)); return true; } var childWorkList = DkmWorkList.Create(null); evalResult.GetChildren(childWorkList, 0, inspectionContext, getChildrenResult => getChildrenResult.EnumContext.GetItems(childWorkList, 0, int.MaxValue, getItemsResult => vars = getItemsResult.Items.OfType<DkmSuccessEvaluationResult>())); childWorkList.Execute(); } }
internal WorkList(DkmWorkList workList, CompletionRoutine<Exception> onException) { InnerWorkList = workList; _onException = onException; _state = State.Initialized; }
public void ManyItemsSync() { const int n = 10000; var value = CreateDkmClrValue(Enumerable.Range(0, n).ToArray()); var evalResult = FormatResult("a", value); IDkmClrResultProvider resultProvider = new CSharpResultProvider(); var workList = new DkmWorkList(); // GetChildren var getChildrenResult = default(DkmGetChildrenAsyncResult); resultProvider.GetChildren(evalResult, workList, n, DefaultInspectionContext, r => getChildrenResult = r); Assert.Equal(workList.Length, 0); Assert.Equal(getChildrenResult.InitialChildren.Length, n); // GetItems var getItemsResult = default(DkmEvaluationEnumAsyncResult); resultProvider.GetItems(getChildrenResult.EnumContext, workList, 0, n, r => getItemsResult = r); Assert.Equal(workList.Length, 0); Assert.Equal(getItemsResult.Items.Length, n); }
public void GetFrameReturnType(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmCompletionRoutine<DkmGetFrameReturnTypeAsyncResult> completionRoutine) { completionRoutine(new DkmGetFrameReturnTypeAsyncResult(null)); }
private void GetItemsAndContinue(EvalResultDataItem dataItem, DkmWorkList workList, int startIndex, int count, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmEvaluationEnumAsyncResult> completionRoutine) { var expansion = dataItem.Expansion; var value = dataItem.Value; var rows = ArrayBuilder<EvalResultDataItem>.GetInstance(); if (expansion != null) { int index = 0; expansion.GetRows(this, rows, inspectionContext, dataItem, value, startIndex, count, visitAll: false, index: ref index); } var numRows = rows.Count; Debug.Assert(count >= numRows); var results = new DkmEvaluationResult[numRows]; var wl = new WorkList(workList, e => completionRoutine(DkmEvaluationEnumAsyncResult.CreateErrorResult(e))); GetEvaluationResultsAndContinue(rows, results, 0, numRows, wl, inspectionContext, value.StackFrame, () => wl.ContinueWith( () => { completionRoutine(new DkmEvaluationEnumAsyncResult(results)); rows.Free(); })); wl.Execute(); }
public void MultipleItemsAsync() { var source = @"using System.Diagnostics; [DebuggerDisplay(""{F}"")] class C { object F; }"; var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib(GetAssembly(source))); using (runtime.Load()) { int n = 10; var type = runtime.GetType("C"); // C[] with alternating null and non-null values. var value = CreateDkmClrValue(Enumerable.Range(0, n).Select(i => (i % 2) == 0 ? type.Instantiate() : null).ToArray()); var evalResult = FormatResult("a", value); IDkmClrResultProvider resultProvider = new CSharpResultProvider(); var workList = new DkmWorkList(); // GetChildren var getChildrenResult = default(DkmGetChildrenAsyncResult); resultProvider.GetChildren(evalResult, workList, n, DefaultInspectionContext, r => getChildrenResult = r); Assert.Equal(workList.Length, 1); workList.Execute(); Assert.Equal(getChildrenResult.InitialChildren.Length, n); // GetItems var getItemsResult = default(DkmEvaluationEnumAsyncResult); resultProvider.GetItems(getChildrenResult.EnumContext, workList, 0, n, r => getItemsResult = r); Assert.Equal(workList.Length, 1); workList.Execute(); Assert.Equal(getItemsResult.Items.Length, n); } }
void IDkmClrResultProvider.GetItems(DkmEvaluationResultEnumContext enumContext, DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine<DkmEvaluationEnumAsyncResult> completionRoutine) { var dataItem = enumContext.GetDataItem<EnumContextDataItem>(); if (dataItem == null) { // We don't know about this result. Call next implementation enumContext.GetItems(workList, startIndex, count, completionRoutine); return; } GetItemsAndContinue(dataItem.EvalResultDataItem, workList, startIndex, count, enumContext.InspectionContext, completionRoutine); }
public void MultipleItemsAndExceptions() { var source = @"using System.Diagnostics; [DebuggerDisplay(""{P}"")] class C { public C(int f) { this.f = f; } private readonly int f; object P { get { if (this.f % 4 == 3) throw new System.ArgumentException(); return this.f; } } }"; var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib(GetAssembly(source))); using (runtime.Load()) { int n = 10; int nFailures = 2; var type = runtime.GetType("C"); var value = CreateDkmClrValue(Enumerable.Range(0, n).Select(i => type.Instantiate(i)).ToArray()); var evalResult = FormatResult("a", value); IDkmClrResultProvider resultProvider = new CSharpResultProvider(); var workList = new DkmWorkList(); // GetChildren var getChildrenResult = default(DkmGetChildrenAsyncResult); resultProvider.GetChildren(evalResult, workList, n, DefaultInspectionContext, r => getChildrenResult = r); Assert.Equal(workList.Length, 1); workList.Execute(); var items = getChildrenResult.InitialChildren; Assert.Equal(items.Length, n); Assert.Equal(items.OfType<DkmFailedEvaluationResult>().Count(), nFailures); // GetItems var getItemsResult = default(DkmEvaluationEnumAsyncResult); resultProvider.GetItems(getChildrenResult.EnumContext, workList, 0, n, r => getItemsResult = r); Assert.Equal(workList.Length, 1); workList.Execute(); items = getItemsResult.Items; Assert.Equal(items.Length, n); Assert.Equal(items.OfType<DkmFailedEvaluationResult>().Count(), nFailures); } }