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))))); }
void IDkmLanguageFrameDecoder.GetFrameReturnType( DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmCompletionRoutine <DkmGetFrameReturnTypeAsyncResult> completionRoutine ) { try { GetNameWithGenericTypeArguments( workList, frame, onSuccess: method => completionRoutine( new DkmGetFrameReturnTypeAsyncResult( _instructionDecoder.GetReturnTypeName(method) ) ), onFailure: e => completionRoutine(DkmGetFrameReturnTypeAsyncResult.CreateErrorResult(e)) ); } catch (NotImplementedMetadataException) { inspectionContext.GetFrameReturnType(workList, frame, completionRoutine); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
void IDkmLanguageFrameDecoder.GetFrameName( DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmVariableInfoFlags argumentFlags, DkmCompletionRoutine <DkmGetFrameNameAsyncResult> completionRoutine) { try { Debug.Assert((argumentFlags & (DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types | DkmVariableInfoFlags.Values)) == argumentFlags, $"Unexpected argumentFlags '{argumentFlags}'"); GetNameWithGenericTypeArguments(inspectionContext, workList, frame, onSuccess: method => GetFrameName(inspectionContext, workList, frame, argumentFlags, completionRoutine, method), onFailure: e => completionRoutine(DkmGetFrameNameAsyncResult.CreateErrorResult(e))); } catch (NotImplementedMetadataException) { inspectionContext.GetFrameName(workList, frame, argumentFlags, completionRoutine); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
private static void EvaluateDebuggerDisplayStringAndContinue( DkmClrValue value, WorkList workList, DkmInspectionContext inspectionContext, DkmClrType targetType, string str, CompletionRoutine <DkmEvaluateDebuggerDisplayStringAsyncResult> onCompleted, CompletionRoutine <Exception> onException) { DkmCompletionRoutine <DkmEvaluateDebuggerDisplayStringAsyncResult> completionRoutine = result => { try { onCompleted(result); } catch (Exception e) when(ExpressionEvaluatorFatalError.ReportNonFatalException(e, DkmComponentManager.ReportCurrentNonFatalException)) { onException(e); } }; if (str == null) { completionRoutine(default(DkmEvaluateDebuggerDisplayStringAsyncResult)); } else { value.EvaluateDebuggerDisplayString(workList.InnerWorkList, inspectionContext, targetType, str, completionRoutine); } }
public void GetResult( DkmWorkList WorkList, DkmClrType DeclaredType, DkmClrCustomTypeInfo CustomTypeInfo, DkmInspectionContext InspectionContext, ReadOnlyCollection <string> FormatSpecifiers, string ResultName, string ResultFullName, DkmCompletionRoutine <DkmEvaluationAsyncResult> CompletionRoutine) { InspectionContext.InspectionSession.InvokeResultProvider( this, MethodId.GetResult, r => { r.GetResult( this, WorkList, DeclaredType, CustomTypeInfo, InspectionContext, FormatSpecifiers, ResultName, ResultFullName, CompletionRoutine); return((object)null); }); }
private void GetChild( DkmEvaluationResult parent, WorkList workList, EvalResult row, DkmCompletionRoutine <DkmEvaluationAsyncResult> completionRoutine) { var inspectionContext = row.InspectionContext; if ((row.Kind != ExpansionKind.Default) || (row.Value == null)) { CreateEvaluationResultAndContinue( row, workList, row.InspectionContext, parent.StackFrame, child => completionRoutine(new DkmEvaluationAsyncResult(child))); } else { var typeDeclaringMember = row.TypeDeclaringMemberAndInfo; var name = (typeDeclaringMember.Type == null) ? row.Name : GetQualifiedMemberName(row.InspectionContext, typeDeclaringMember, row.Name, FullNameProvider); row.Value.GetResult( workList.InnerWorkList, row.DeclaredTypeAndInfo.ClrType, row.DeclaredTypeAndInfo.Info, row.InspectionContext, Formatter.NoFormatSpecifiers, name, row.FullName, result => workList.ContinueWith(() => completionRoutine(result))); } }
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); } }
/// <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)); }
/// <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)); }
public void GetItems(DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine <DkmEvaluationEnumAsyncResult> completionRoutine) { InspectionContext.InspectionSession.InvokeResultProvider( MethodId.GetItems, r => { r.GetItems(this, workList, startIndex, count, completionRoutine); return((object)null); }); }
public void GetChildren(DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmGetChildrenAsyncResult> completionRoutine) { InspectionContext.InspectionSession.InvokeResultProvider( MethodId.GetChildren, r => { r.GetChildren(this, workList, initialRequestSize, inspectionContext, completionRoutine); return (object)null; }); }
void IDkmClrResultProvider.GetItems( DkmEvaluationResultEnumContext enumContext, DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine <DkmEvaluationEnumAsyncResult> completionRoutine ) { enumContext.GetItems(workList, startIndex, count, completionRoutine); }
public void GetItems(DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine<DkmEvaluationEnumAsyncResult> completionRoutine) { InspectionContext.InspectionSession.InvokeResultProvider( MethodId.GetItems, r => { r.GetItems(this, workList, startIndex, count, completionRoutine); return (object)null; }); }
/// <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(); }
void IDkmClrResultProvider.GetChildren( DkmEvaluationResult evaluationResult, DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine <DkmGetChildrenAsyncResult> completionRoutine ) { evaluationResult.GetChildren( workList, initialRequestSize, inspectionContext, completionRoutine ); }
private void GetEvaluationResultsAndContinue( DkmEvaluationResult parent, ArrayBuilder <EvalResult> rows, DkmEvaluationResult[] results, int index, int numRows, WorkList workList, DkmInspectionContext inspectionContext, CompletionRoutine onCompleted, CompletionRoutine <Exception> onException) { DkmCompletionRoutine <DkmEvaluationAsyncResult> completionRoutine = result => { try { results[index] = result.Result; GetEvaluationResultsAndContinue(parent, rows, results, index + 1, numRows, workList, inspectionContext, onCompleted, onException); } catch (Exception e) { onException(e); } }; if (index < numRows) { GetChild( parent, workList, rows[index], child => workList.ContinueWith(() => completionRoutine(child))); } else { onCompleted(); } }
public void GetChildren( DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine <DkmGetChildrenAsyncResult> completionRoutine ) { InspectionContext.InspectionSession.InvokeResultProvider( this, MethodId.GetChildren, r => { r.GetChildren( this, workList, initialRequestSize, inspectionContext, completionRoutine ); return((object)null); } ); }
/// <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(); } }
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 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)); }
/// <remarks> /// Very simple expression evaluation (may not support all syntax supported by Concord). /// </remarks> public void EvaluateDebuggerDisplayString(DkmWorkList workList, DkmInspectionContext inspectionContext, DkmClrType targetType, string formatString, DkmCompletionRoutine<DkmEvaluateDebuggerDisplayStringAsyncResult> completionRoutine) { Debug.Assert(!this.IsNull, "Not supported by VIL"); if (inspectionContext == null) { throw new ArgumentNullException(nameof(inspectionContext)); } var pooled = PooledStringBuilder.GetInstance(); var builder = pooled.Builder; int openPos = -1; int length = formatString.Length; for (int i = 0; i < length; i++) { char ch = formatString[i]; if (ch == '{') { if (openPos >= 0) { throw new ArgumentException(string.Format("Nested braces in '{0}'", formatString)); } openPos = i; } else if (ch == '}') { if (openPos < 0) { throw new ArgumentException(string.Format("Unmatched closing brace in '{0}'", formatString)); } string name = formatString.Substring(openPos + 1, i - openPos - 1); openPos = -1; var formatSpecifiers = Formatter.NoFormatSpecifiers; int commaIndex = name.IndexOf(','); if (commaIndex >= 0) { var rawFormatSpecifiers = name.Substring(commaIndex + 1).Split(','); var trimmedFormatSpecifiers = ArrayBuilder<string>.GetInstance(rawFormatSpecifiers.Length); trimmedFormatSpecifiers.AddRange(rawFormatSpecifiers.Select(fs => fs.Trim())); formatSpecifiers = trimmedFormatSpecifiers.ToImmutableAndFree(); foreach (var formatSpecifier in formatSpecifiers) { if (formatSpecifier == "nq") { inspectionContext = new DkmInspectionContext(inspectionContext.InspectionSession, inspectionContext.EvaluationFlags | DkmEvaluationFlags.NoQuotes, inspectionContext.Radix, inspectionContext.RuntimeInstance); } // If we need to support additional format specifiers, add them here... } name = name.Substring(0, commaIndex); } var type = ((TypeImpl)this.Type.GetLmrType()).Type; const System.Reflection.BindingFlags bindingFlags = System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static; DkmClrValue exprValue; var appDomain = this.Type.AppDomain; var field = type.GetField(name, bindingFlags); if (field != null) { var fieldValue = field.GetValue(RawValue); exprValue = new DkmClrValue( fieldValue, fieldValue, DkmClrType.Create(appDomain, (TypeImpl)((fieldValue == null) ? field.FieldType : fieldValue.GetType())), alias: null, evalFlags: GetEvaluationResultFlags(fieldValue), valueFlags: DkmClrValueFlags.None); } else { var property = type.GetProperty(name, bindingFlags); if (property != null) { var propertyValue = property.GetValue(RawValue); exprValue = new DkmClrValue( propertyValue, propertyValue, DkmClrType.Create(appDomain, (TypeImpl)((propertyValue == null) ? property.PropertyType : propertyValue.GetType())), alias: null, evalFlags: GetEvaluationResultFlags(propertyValue), valueFlags: DkmClrValueFlags.None); } else { var openParenIndex = name.IndexOf('('); if (openParenIndex >= 0) { name = name.Substring(0, openParenIndex); } var method = type.GetMethod(name, bindingFlags); // The real implementation requires parens on method invocations, so // we'll return error if there wasn't at least an open paren... if ((openParenIndex >= 0) && method != null) { var methodValue = method.Invoke(RawValue, new object[] { }); exprValue = new DkmClrValue( methodValue, methodValue, DkmClrType.Create(appDomain, (TypeImpl)((methodValue == null) ? method.ReturnType : methodValue.GetType())), alias: null, evalFlags: GetEvaluationResultFlags(methodValue), valueFlags: DkmClrValueFlags.None); } else { var stringValue = "Problem evaluating expression"; var stringType = DkmClrType.Create(appDomain, (TypeImpl)typeof(string)); exprValue = new DkmClrValue( stringValue, stringValue, stringType, alias: null, evalFlags: DkmEvaluationResultFlags.None, valueFlags: DkmClrValueFlags.Error); } } } builder.Append(exprValue.GetValueString(inspectionContext, formatSpecifiers)); // Re-enter the formatter. } else if (openPos < 0) { builder.Append(ch); } } if (openPos >= 0) { throw new ArgumentException(string.Format("Unmatched open brace in '{0}'", formatString)); } workList.AddWork(() => completionRoutine(new DkmEvaluateDebuggerDisplayStringAsyncResult(pooled.ToStringAndFree()))); }
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); }
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); }
void IDkmLanguageExpressionEvaluator.GetItems(DkmEvaluationResultEnumContext enumContext, DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine <DkmEvaluationEnumAsyncResult> completionRoutine) { var ee = enumContext.StackFrame.Process.GetDataItem <ExpressionEvaluator>(); if (ee == null) { Debug.Fail("GetItems called, but no instance of ExpressionEvaluator exists in this DkmProcess to handle it."); throw new InvalidOperationException(); } ee.GetItems(enumContext, workList, startIndex, count, 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)); }
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; } var expansion = dataItem.Expansion; if (expansion == null) { var enumContext = DkmEvaluationResultEnumContext.Create(0, evaluationResult.StackFrame, inspectionContext, new EnumContextDataItem(evaluationResult)); completionRoutine(new DkmGetChildrenAsyncResult(new DkmEvaluationResult[0], enumContext)); return; } // Evaluate children with InspectionContext that is not the root. inspectionContext = inspectionContext.With(NotRoot); var rows = ArrayBuilder <EvalResult> .GetInstance(); int index = 0; 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]; CompletionRoutine <Exception> onException = e => completionRoutine(DkmGetChildrenAsyncResult.CreateErrorResult(e)); var wl = new WorkList(workList, onException); wl.ContinueWith(() => GetEvaluationResultsAndContinue(evaluationResult, rows, initialChildren, 0, numRows, wl, inspectionContext, () => wl.ContinueWith( () => { var enumContext = DkmEvaluationResultEnumContext.Create(index, evaluationResult.StackFrame, inspectionContext, new EnumContextDataItem(evaluationResult)); completionRoutine(new DkmGetChildrenAsyncResult(initialChildren, enumContext)); rows.Free(); }), onException)); }
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)); }
public void GetFrameReturnType(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmCompletionRoutine<DkmGetFrameReturnTypeAsyncResult> completionRoutine) { completionRoutine(new DkmGetFrameReturnTypeAsyncResult(null)); }
void IDkmClrResultProvider.GetChildren(DkmEvaluationResult evaluationResult, DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmGetChildrenAsyncResult> completionRoutine) { evaluationResult.GetChildren(workList, initialRequestSize, inspectionContext, completionRoutine); }
void IDkmClrResultProvider.GetItems(DkmEvaluationResultEnumContext enumContext, DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine<DkmEvaluationEnumAsyncResult> completionRoutine) { enumContext.GetItems(workList, startIndex, count, completionRoutine); }
void IDkmLanguageFrameDecoder.GetFrameReturnType(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmCompletionRoutine <DkmGetFrameReturnTypeAsyncResult> completionRoutine) { if (frame.RuntimeInstance.Id.RuntimeType != Guids.PythonRuntimeTypeGuid) { Debug.Fail("GetFrameReturnType called on a non-Python frame."); throw new NotSupportedException(); } var filter = frame.Process.GetDataItem <CallStackFilter>(); if (filter == null) { Debug.Fail("GetFrameReturnType called, but no instance of CallStackFilter exists in this DkmProcess to handle it."); throw new InvalidOperationException(); } filter.GetFrameReturnType(inspectionContext, workList, frame, completionRoutine); }
void IDkmLanguageExpressionEvaluator.GetChildren(DkmEvaluationResult result, DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine <DkmGetChildrenAsyncResult> completionRoutine) { var ee = result.StackFrame.Process.GetDataItem <ExpressionEvaluator>(); if (ee == null) { Debug.Fail("GetChildren called, but no instance of ExpressionEvaluator exists in this DkmProcess to handle it."); throw new InvalidOperationException(); } ee.GetChildren(result, workList, initialRequestSize, inspectionContext, completionRoutine); }
public virtual void GetItems(DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine<DkmEvaluationEnumAsyncResult> completionRoutine) { throw new NotImplementedException(); }
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(); }
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))))); }
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); } }); }
private void GetChild( DkmEvaluationResult parent, WorkList workList, EvalResult row, DkmCompletionRoutine<DkmEvaluationAsyncResult> completionRoutine) { var inspectionContext = row.InspectionContext; if ((row.Kind != ExpansionKind.Default) || (row.Value == null)) { CreateEvaluationResultAndContinue( row, workList, row.InspectionContext, parent.StackFrame, child => completionRoutine(new DkmEvaluationAsyncResult(child))); } else { var typeDeclaringMember = row.TypeDeclaringMemberAndInfo; var name = (typeDeclaringMember.Type == null) ? row.Name : GetQualifiedMemberName(row.InspectionContext, typeDeclaringMember, row.Name, FullNameProvider); row.Value.GetResult( workList.InnerWorkList, row.DeclaredTypeAndInfo.ClrType, row.DeclaredTypeAndInfo.Info, row.InspectionContext, Formatter.NoFormatSpecifiers, name, row.FullName, result => workList.ContinueWith(() => completionRoutine(result))); } }
public void GetResult( DkmWorkList WorkList, DkmClrType DeclaredType, DkmClrCustomTypeInfo CustomTypeInfo, DkmInspectionContext InspectionContext, ReadOnlyCollection<string> FormatSpecifiers, string ResultName, string ResultFullName, DkmCompletionRoutine<DkmEvaluationAsyncResult> CompletionRoutine) { InspectionContext.InspectionSession.InvokeResultProvider( this, MethodId.GetResult, r => { r.GetResult( this, WorkList, DeclaredType, CustomTypeInfo, InspectionContext, FormatSpecifiers, ResultName, ResultFullName, CompletionRoutine); return (object)null; }); }
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)); }
public void GetChildren(DkmEvaluationResult result, DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmGetChildrenAsyncResult> completionRoutine) { CppEvaluationResult.GetChildren(workList, initialRequestSize, CppEvaluationResult.InspectionContext, (cppResult) => { completionRoutine(cppResult); }); }
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; } var expansion = dataItem.Expansion; if (expansion == null) { var enumContext = DkmEvaluationResultEnumContext.Create(0, evaluationResult.StackFrame, inspectionContext, new EnumContextDataItem(evaluationResult)); completionRoutine(new DkmGetChildrenAsyncResult(new DkmEvaluationResult[0], enumContext)); return; } // Evaluate children with InspectionContext that is not the root. inspectionContext = inspectionContext.With(NotRoot); var rows = ArrayBuilder<EvalResult>.GetInstance(); int index = 0; 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]; CompletionRoutine<Exception> onException = e => completionRoutine(DkmGetChildrenAsyncResult.CreateErrorResult(e)); var wl = new WorkList(workList, onException); wl.ContinueWith(() => GetEvaluationResultsAndContinue(evaluationResult, rows, initialChildren, 0, numRows, wl, inspectionContext, () => wl.ContinueWith( () => { var enumContext = DkmEvaluationResultEnumContext.Create(index, evaluationResult.StackFrame, inspectionContext, new EnumContextDataItem(evaluationResult)); completionRoutine(new DkmGetChildrenAsyncResult(initialChildren, enumContext)); rows.Free(); }), onException)); }
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 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)); }
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); } }); }); } }); }); }
public void GetFrameReturnType(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmCompletionRoutine <DkmGetFrameReturnTypeAsyncResult> completionRoutine) { completionRoutine(new DkmGetFrameReturnTypeAsyncResult(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))); } }
private void GetFrameName( DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmVariableInfoFlags argumentFlags, DkmCompletionRoutine <DkmGetFrameNameAsyncResult> completionRoutine, TMethodSymbol method) { var includeParameterTypes = argumentFlags.Includes(DkmVariableInfoFlags.Types); var includeParameterNames = argumentFlags.Includes(DkmVariableInfoFlags.Names); if (argumentFlags.Includes(DkmVariableInfoFlags.Values)) { // No need to compute the Expandable bit on // argument values since that can be expensive. inspectionContext = DkmInspectionContext.Create( inspectionContext.InspectionSession, inspectionContext.RuntimeInstance, inspectionContext.Thread, inspectionContext.Timeout, inspectionContext.EvaluationFlags | DkmEvaluationFlags.NoExpansion, inspectionContext.FuncEvalFlags, inspectionContext.Radix, inspectionContext.Language, inspectionContext.ReturnValue, inspectionContext.AdditionalVisualizationData, inspectionContext.AdditionalVisualizationDataPriority, inspectionContext.ReturnValues); // GetFrameArguments returns an array of formatted argument values. We'll pass // ourselves (GetFrameName) as the continuation of the GetFrameArguments call. inspectionContext.GetFrameArguments( workList, frame, result => { var argumentValues = result.Arguments; try { var builder = ArrayBuilder <string> .GetInstance(); foreach (var argument in argumentValues) { var formattedArgument = argument as DkmSuccessEvaluationResult; // Not expecting Expandable bit, at least not from this EE. Debug.Assert((formattedArgument == null) || (formattedArgument.Flags & DkmEvaluationResultFlags.Expandable) == 0); builder.Add(formattedArgument?.Value); } var frameName = _instructionDecoder.GetName(method, includeParameterTypes, includeParameterNames, builder); builder.Free(); completionRoutine(new DkmGetFrameNameAsyncResult(frameName)); } catch (Exception e) when(ExpressionEvaluatorFatalError.ReportNonFatalException(e, DkmComponentManager.ReportCurrentNonFatalException)) { completionRoutine(DkmGetFrameNameAsyncResult.CreateErrorResult(e)); } finally { foreach (var argument in argumentValues) { argument.Close(); } } }); } else { var frameName = _instructionDecoder.GetName(method, includeParameterTypes, includeParameterNames, null); completionRoutine(new DkmGetFrameNameAsyncResult(frameName)); } }
void IDkmLanguageExpressionEvaluator.GetFrameLocals(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame stackFrame, DkmCompletionRoutine <DkmGetFrameLocalsAsyncResult> completionRoutine) { if (stackFrame.RuntimeInstance.Id.RuntimeType != Guids.PythonRuntimeTypeGuid) { Debug.Fail("GetFrameLocals called on a non-Python frame."); throw new NotSupportedException(); } var ee = stackFrame.Process.GetDataItem <ExpressionEvaluator>(); if (ee == null) { Debug.Fail("GetFrameLocals called, but no instance of ExpressionEvaluator exists in this DkmProcess to handle it."); throw new InvalidOperationException(); } ee.GetFrameLocals(inspectionContext, workList, stackFrame, completionRoutine); }
/// <remarks> /// Very simple expression evaluation (may not support all syntax supported by Concord). /// </remarks> public void EvaluateDebuggerDisplayString(DkmWorkList workList, DkmInspectionContext inspectionContext, DkmClrType targetType, string formatString, DkmCompletionRoutine <DkmEvaluateDebuggerDisplayStringAsyncResult> completionRoutine) { Debug.Assert(!this.IsNull, "Not supported by VIL"); if (inspectionContext == null) { throw new ArgumentNullException(nameof(inspectionContext)); } var pooled = PooledStringBuilder.GetInstance(); var builder = pooled.Builder; int openPos = -1; int length = formatString.Length; for (int i = 0; i < length; i++) { char ch = formatString[i]; if (ch == '{') { if (openPos >= 0) { throw new ArgumentException(string.Format("Nested braces in '{0}'", formatString)); } openPos = i; } else if (ch == '}') { if (openPos < 0) { throw new ArgumentException(string.Format("Unmatched closing brace in '{0}'", formatString)); } string name = formatString.Substring(openPos + 1, i - openPos - 1); openPos = -1; var formatSpecifiers = Formatter.NoFormatSpecifiers; int commaIndex = name.IndexOf(','); if (commaIndex >= 0) { var rawFormatSpecifiers = name.Substring(commaIndex + 1).Split(','); var trimmedFormatSpecifiers = ArrayBuilder <string> .GetInstance(rawFormatSpecifiers.Length); trimmedFormatSpecifiers.AddRange(rawFormatSpecifiers.Select(fs => fs.Trim())); formatSpecifiers = trimmedFormatSpecifiers.ToImmutableAndFree(); foreach (var formatSpecifier in formatSpecifiers) { if (formatSpecifier == "nq") { inspectionContext = new DkmInspectionContext(_formatter, inspectionContext.EvaluationFlags | DkmEvaluationFlags.NoQuotes, inspectionContext.Radix, inspectionContext.RuntimeInstance); } // If we need to support additional format specifiers, add them here... } name = name.Substring(0, commaIndex); } var type = ((TypeImpl)this.Type.GetLmrType()).Type; const System.Reflection.BindingFlags bindingFlags = System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static; DkmClrValue exprValue; var appDomain = this.Type.AppDomain; var field = type.GetField(name, bindingFlags); if (field != null) { var fieldValue = field.GetValue(RawValue); exprValue = new DkmClrValue( fieldValue, fieldValue, DkmClrType.Create(appDomain, (TypeImpl)((fieldValue == null) ? field.FieldType : fieldValue.GetType())), alias: null, formatter: _formatter, evalFlags: GetEvaluationResultFlags(fieldValue), valueFlags: DkmClrValueFlags.None); } else { var property = type.GetProperty(name, bindingFlags); if (property != null) { var propertyValue = property.GetValue(RawValue); exprValue = new DkmClrValue( propertyValue, propertyValue, DkmClrType.Create(appDomain, (TypeImpl)((propertyValue == null) ? property.PropertyType : propertyValue.GetType())), alias: null, formatter: _formatter, evalFlags: GetEvaluationResultFlags(propertyValue), valueFlags: DkmClrValueFlags.None); } else { var openParenIndex = name.IndexOf('('); if (openParenIndex >= 0) { name = name.Substring(0, openParenIndex); } var method = type.GetMethod(name, bindingFlags); // The real implementation requires parens on method invocations, so // we'll return error if there wasn't at least an open paren... if ((openParenIndex >= 0) && method != null) { var methodValue = method.Invoke(RawValue, new object[] { }); exprValue = new DkmClrValue( methodValue, methodValue, DkmClrType.Create(appDomain, (TypeImpl)((methodValue == null) ? method.ReturnType : methodValue.GetType())), alias: null, formatter: _formatter, evalFlags: GetEvaluationResultFlags(methodValue), valueFlags: DkmClrValueFlags.None); } else { var stringValue = "Problem evaluating expression"; var stringType = DkmClrType.Create(appDomain, (TypeImpl)typeof(string)); exprValue = new DkmClrValue( stringValue, stringValue, stringType, alias: null, formatter: _formatter, evalFlags: DkmEvaluationResultFlags.None, valueFlags: DkmClrValueFlags.Error); } } } builder.Append(exprValue.GetValueString(inspectionContext, formatSpecifiers)); // Re-enter the formatter. } else if (openPos < 0) { builder.Append(ch); } } if (openPos >= 0) { throw new ArgumentException(string.Format("Unmatched open brace in '{0}'", formatString)); } workList.AddWork(() => completionRoutine(new DkmEvaluateDebuggerDisplayStringAsyncResult(pooled.ToStringAndFree()))); }
void IDkmLanguageExpressionEvaluator.GetFrameArguments(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmCompletionRoutine <DkmGetFrameArgumentsAsyncResult> completionRoutine) { throw new NotImplementedException(); }
void IDkmClrResultProvider.GetResult(DkmClrValue value, DkmWorkList workList, DkmClrType declaredType, DkmInspectionContext inspectionContext, ReadOnlyCollection <string> formatSpecifiers, string resultName, string resultFullName, DkmCompletionRoutine <DkmEvaluationAsyncResult> completionRoutine) { // TODO: Use full name GetRootResultAndContinue(value, workList, declaredType, inspectionContext, resultName, result => ContinueWithExceptionHandling( () => completionRoutine(new DkmEvaluationAsyncResult(result)), e => completionRoutine(DkmEvaluationAsyncResult.CreateErrorResult(e)))); }
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]; GetEvaluationResultsAndContinue(rows, initialChildren, 0, numRows, workList, inspectionContext, stackFrame, () => ContinueWithExceptionHandling( () => { var enumContext = DkmEvaluationResultEnumContext.Create(index, stackFrame, inspectionContext, new EnumContextDataItem(dataItem)); completionRoutine(new DkmGetChildrenAsyncResult(initialChildren, enumContext)); rows.Free(); }, e => completionRoutine(DkmGetChildrenAsyncResult.CreateErrorResult(e)))); }
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]; GetEvaluationResultsAndContinue(rows, results, 0, numRows, workList, inspectionContext, value.StackFrame, () => ContinueWithExceptionHandling( () => { completionRoutine(new DkmEvaluationEnumAsyncResult(results)); rows.Free(); }, e => completionRoutine(DkmEvaluationEnumAsyncResult.CreateErrorResult(e)))); }
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(); }
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; } var stackFrame = evaluationResult.StackFrame; GetChildrenAndContinue(dataItem, workList, stackFrame, initialRequestSize, inspectionContext, completionRoutine); }
public virtual void GetChildren(DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmGetChildrenAsyncResult> completionRoutine) { throw new NotImplementedException(); }
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; } }