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; }); }
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; }); }
internal DkmEvaluationResult[] GetChildren(DkmEvaluationResult evalResult, int initialRequestSize, DkmInspectionContext inspectionContext, out DkmEvaluationResultEnumContext enumContext) { DkmGetChildrenAsyncResult getChildrenResult = default(DkmGetChildrenAsyncResult); var workList = new DkmWorkList(); _resultProvider.GetChildren(evalResult, workList, initialRequestSize, inspectionContext ?? DefaultInspectionContext, r => { getChildrenResult = r; }); workList.Execute(); var exception = getChildrenResult.Exception; if (exception != null) { ExceptionDispatchInfo.Capture(exception).Throw(); } enumContext = getChildrenResult.EnumContext; return(getChildrenResult.InitialChildren); }
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( 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; } }
void IDkmLanguageFrameDecoder.GetFrameReturnType( DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmCompletionRoutine <DkmGetFrameReturnTypeAsyncResult> completionRoutine) { try { GetNameWithGenericTypeArguments(inspectionContext, workList, frame, onSuccess: method => completionRoutine(new DkmGetFrameReturnTypeAsyncResult(_instructionDecoder.GetReturnTypeName(method))), onFailure: e => completionRoutine(DkmGetFrameReturnTypeAsyncResult.CreateErrorResult(e))); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
internal DkmEvaluationAsyncResult FormatAsyncResult(string name, string fullName, DkmClrValue value, DkmClrType declaredType = null, DkmClrCustomTypeInfo declaredTypeInfo = null, DkmInspectionContext inspectionContext = null) { DkmEvaluationAsyncResult asyncResult = default(DkmEvaluationAsyncResult); var workList = new DkmWorkList(); value.GetResult( workList, DeclaredType: declaredType ?? value.Type, CustomTypeInfo: declaredTypeInfo, InspectionContext: inspectionContext ?? DefaultInspectionContext, FormatSpecifiers: Formatter.NoFormatSpecifiers, ResultName: name, ResultFullName: fullName, CompletionRoutine: r => asyncResult = r); workList.Execute(); return(asyncResult); }
/// <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) { try { string name = TryGetFrameNameHelper(inspectionContext, frame, argumentFlags) ?? "<Unknown Method>"; completionRoutine(new DkmGetFrameNameAsyncResult(name)); } catch (Exception) { inspectionContext.GetFrameName(workList, frame, argumentFlags, completionRoutine); } }
internal DkmEvaluationResult FormatResult(string name, string fullName, DkmClrValue value, DkmClrType declaredType = null, DkmInspectionContext inspectionContext = null) { DkmEvaluationResult evaluationResult = null; var workList = new DkmWorkList(); _resultProvider.GetResult( value, workList, declaredType: declaredType ?? value.Type, inspectionContext: inspectionContext ?? DefaultInspectionContext, formatSpecifiers: Formatter.NoFormatSpecifiers, resultName: name, resultFullName: null, completionRoutine: asyncResult => evaluationResult = asyncResult.Result); workList.Execute(); return(evaluationResult); }
public void GetItems( DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine <DkmEvaluationEnumAsyncResult> completionRoutine ) { InspectionContext.InspectionSession.InvokeResultProvider( this, MethodId.GetItems, r => { r.GetItems(this, workList, startIndex, count, completionRoutine); return((object)null); } ); }
internal DkmEvaluationResult FormatResult(string name, string fullName, DkmClrValue value, DkmClrType declaredType = null, bool[] declaredTypeInfo = null, DkmInspectionContext inspectionContext = null) { DkmEvaluationResult evaluationResult = null; var workList = new DkmWorkList(); _resultProvider.GetResult( value, workList, declaredType: declaredType ?? value.Type, customTypeInfo: new DynamicFlagsCustomTypeInfo(declaredTypeInfo == null ? null : new BitArray(declaredTypeInfo)).GetCustomTypeInfo(), inspectionContext: inspectionContext ?? DefaultInspectionContext, formatSpecifiers: Formatter.NoFormatSpecifiers, resultName: name, resultFullName: null, completionRoutine: asyncResult => evaluationResult = asyncResult.Result); workList.Execute(); return(evaluationResult); }
private void GetNameWithGenericTypeArguments( DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, Action <TMethodSymbol> onSuccess, Action <Exception> onFailure) { // NOTE: We could always call GetClrGenericParameters, pass them to GetMethod and have that // return a constructed method symbol, but it seems unwise to call GetClrGenericParameters // for all frames (as this call requires a round-trip to the debuggee process). var instructionAddress = (DkmClrInstructionAddress)frame.InstructionAddress; var compilation = _instructionDecoder.GetCompilation(instructionAddress.ModuleInstance); var method = _instructionDecoder.GetMethod(compilation, instructionAddress); var typeParameters = _instructionDecoder.GetAllTypeParameters(method); if (!typeParameters.IsEmpty) { frame.GetClrGenericParameters( workList, result => { try { // DkmGetClrGenericParametersAsyncResult.ParameterTypeNames will throw if ErrorCode != 0. var serializedTypeNames = (result.ErrorCode == 0) ? result.ParameterTypeNames : null; var typeArguments = _instructionDecoder.GetTypeSymbols(compilation, method, serializedTypeNames); if (!typeArguments.IsEmpty) { method = _instructionDecoder.ConstructMethod(method, typeParameters, typeArguments); } onSuccess(method); } catch (Exception e) { onFailure(e); } }); } else { onSuccess(method); } }
private void OnModuleLoad(DkmModuleInstance moduleInstance, DkmWorkList workList) { var module = moduleInstance as DkmClrModuleInstance; Debug.Assert(module != null); // <Filter><RuntimeId RequiredValue="DkmRuntimeId.Clr"/></Filter> should ensure this. if (module == null) { // Only interested in managed modules. return; } if (module.Module == null) { // Only resolve breakpoints if symbols have been loaded. return; } OnModuleLoad(module.Process, module, OnFunctionResolved(workList)); }
internal static DkmEvaluationResult ExecuteRawExpression(string expression, DkmInspectionSession inspectionSession, DkmThread thread, DkmStackWalkFrame input, DkmRuntimeInstance runtimeInstance, DkmEvaluationFlags flags) { var compilerId = new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.Cpp); var language = DkmLanguage.Create("C++", compilerId); var languageExpression = DkmLanguageExpression.Create(language, DkmEvaluationFlags.None, expression, null); DkmInspectionContext inspectionContext; LuaWorkerConnectionWrapper workerConnectionWrapper = inspectionSession.Process.GetDataItem <LuaWorkerConnectionWrapper>(); if (workerConnectionWrapper != null) { inspectionContext = workerConnectionWrapper.CreateInspectionSession(inspectionSession, runtimeInstance, thread, flags, language); } else { inspectionContext = DkmInspectionContext.Create(inspectionSession, runtimeInstance, thread, 200, flags, DkmFuncEvalFlags.None, 10, language, null); } var workList = DkmWorkList.Create(null); try { DkmEvaluationResult result = null; inspectionContext.EvaluateExpression(workList, languageExpression, input, res => { if (res.ErrorCode == 0) { result = res.ResultObject; } }); workList.Execute(); return(result); } catch (OperationCanceledException) { return(null); } }
private int QueryColumnCount() { int columnCount = 0; DkmLanguageExpression expr = null; try { DkmWorkList workList = DkmWorkList.Create(null); SqliteVisualizerException ex = null; expr = this.AddFuncEval( workList, $"sqlite3_column_count(*(sqlite3_stmt **){this.procMemForQuery})", (r) => { DkmSuccessEvaluationResult suc; if (!this.VerifySuccess(r, out suc)) { ex = new SqliteVisualizerException(Resources.ErrMsg_FuncEvalFailed, r.FullName); return; } columnCount = (int)suc.Address.Value; }); workList.Execute(); if (ex != null) { throw ex; } } finally { if (expr != null) { expr.Close(); } } return(columnCount); }
private void GetNameWithGenericTypeArguments( DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, Action <TMethodSymbol> onSuccess, Action <Exception> onFailure) { // NOTE: We could always call GetClrGenericParameters, pass them to GetMethod and have that // return a constructed method symbol, but it seems unwise to call GetClrGenericParameters // for all frames (as this call requires a round-trip to the debuggee process). var instructionAddress = (DkmClrInstructionAddress)frame.InstructionAddress; var compilation = _instructionDecoder.GetCompilation(instructionAddress.ModuleInstance); var method = _instructionDecoder.GetMethod(compilation, instructionAddress); var typeParameters = _instructionDecoder.GetAllTypeParameters(method); if (!typeParameters.IsEmpty) { frame.GetClrGenericParameters( workList, result => { try { var typeArguments = _instructionDecoder.GetTypeSymbols(compilation, method, result.ParameterTypeNames); if (!typeArguments.IsEmpty) { method = _instructionDecoder.ConstructMethod(method, typeParameters, typeArguments); } onSuccess(method); } catch (Exception e) when(ExpressionEvaluatorFatalError.ReportNonFatalException(e, DkmComponentManager.ReportCurrentNonFatalException)) { onFailure(e); } }); } else { onSuccess(method); } }
private bool EvaluateExpression(string expression, Action <DkmSuccessEvaluationResult> onSuccess) { var workList = DkmWorkList.Create(null); var success = false; _inspectionContext.EvaluateExpression(workList, CppExpression(expression), _frame, res => { var resObj = res.ResultObject; var result = resObj as DkmSuccessEvaluationResult; if (result != null) { success = true; onSuccess(result); } resObj.Close(); }); workList.Execute(); return(success); }
public void OnLoadComplete(DkmProcess process, DkmWorkList workList, DkmEventDescriptor eventDescriptor) { _enabled = true; DisposeStreams(); if (_debugPane == null) { IVsOutputWindow outWindow = Package.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow; Guid debugPaneGuid = VSConstants.GUID_OutWindowDebugPane; outWindow.GetPane(ref debugPaneGuid, out _debugPane); } var env = Environment.GetEnvironmentVariable("UNITY_MIXED_CALLSTACK"); if (env == null || env == "0") // plugin not enabled { _debugPane.OutputString("Warning: To use the UnityMixedCallstack plugin please set the environment variable UNITY_MIXED_CALLSTACK=1 and relaunch Unity and Visual Studio\n"); _debugPane.Activate(); _enabled = false; } }
> OnFunctionResolved(DkmWorkList workList) { return(( DkmClrModuleInstance module, DkmRuntimeFunctionResolutionRequest request, int token, int version, int ilOffset ) => { var address = DkmClrInstructionAddress.Create( module.RuntimeInstance, module, new DkmClrMethodId(Token: token, Version: (uint)version), NativeOffset: uint.MaxValue, ILOffset: (uint)ilOffset, CPUInstruction: null ); // Use async overload of OnFunctionResolved to avoid deadlock. request.OnFunctionResolved(workList, address, result => { }); }); }
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); } ); }
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)); } }
private void FinalizeQuery() { DkmLanguageExpression expr = null; try { SqliteVisualizerException ex = null; DkmWorkList workList = DkmWorkList.Create(null); expr = this.AddFuncEval( workList, $"sqlite3_finalize(*(sqlite3_stmt **){this.procMemForQuery})", (r) => { DkmSuccessEvaluationResult suc; if (!this.VerifySuccess(r, out suc)) { ex = new SqliteVisualizerException(Resources.ErrMsg_FuncEvalFailed, r.FullName); return; } }); workList.Execute(); if (ex != null) { throw ex; } } finally { if (expr != null) { expr.Close(); } } }
private void PrepareQuery() { DkmLanguageExpression expr = null; try { SqliteVisualizerException ex = null; DkmWorkList workList = DkmWorkList.Create(null); expr = this.AddFuncEval( workList, $"sqlite3_prepare({sqliteInstanceName}, \"{query}\", {query.Length + 1}, (sqlite3_stmt **){this.procMemForQuery}, nullptr)", (r) => { DkmSuccessEvaluationResult suc; if (!this.VerifySuccess(r, out suc)) { ex = new SqliteVisualizerException(Resources.ErrMsg_PrepareFailed, r.FullName); return; } }); workList.Execute(); if (ex != null) { throw ex; } } finally { if (expr != null) { expr.Close(); } } }
public virtual void GetChildren(DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmGetChildrenAsyncResult> completionRoutine) { throw new NotImplementedException(); }
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); }
public void OnBeginStepOut(DkmThread thread) { // When we're stepping out while in Python code, there are two possibilities. Either the stack looks like this: // // PythonFrame1 // PythonFrame2 // // or else it looks like this: // // PythonFrame // [Native to Python transition] // NativeFrame // // In both cases, we use native breakpoints on the return address to catch the end of step-out operation. // For Python-to-native step-out, this is the only option. For Python-to-Python, it would seem that TraceFunc // can detect it via PyTrace_RETURN, but it doesn't actually know whether the return is to Python or to // native at the point where it's reported - and, in any case, we need to let PyEval_EvalFrameEx to return // before reporting the completion of that step-out (otherwise we will show the returning frame in call stack). // Find the destination for step-out by walking the call stack and finding either the first native frame // outside of Python and helper DLLs, or the second Python frame. var inspectionSession = DkmInspectionSession.Create(_process, null); var frameFormatOptions = new DkmFrameFormatOptions(DkmVariableInfoFlags.None, DkmFrameNameFormatOptions.None, DkmEvaluationFlags.None, 10000, 10); var stackContext = DkmStackContext.Create(inspectionSession, thread, DkmCallStackFilterOptions.None, frameFormatOptions, null, null); DkmStackFrame frame = null; for (int pyFrameCount = 0; pyFrameCount != 2;) { DkmStackFrame[] frames = null; var workList = DkmWorkList.Create(null); stackContext.GetNextFrames(workList, 1, (result) => { frames = result.Frames; }); workList.Execute(); if (frames == null || frames.Length != 1) { return; } frame = frames[0]; var frameModuleInstance = frame.ModuleInstance; if (frameModuleInstance is DkmNativeModuleInstance && frameModuleInstance != _pyrtInfo.DLLs.Python && frameModuleInstance != _pyrtInfo.DLLs.DebuggerHelper && frameModuleInstance != _pyrtInfo.DLLs.CTypes) { break; } else if (frame.RuntimeInstance != null && frame.RuntimeInstance.Id.RuntimeType == Guids.PythonRuntimeTypeGuid) { ++pyFrameCount; } } var nativeAddr = frame.InstructionAddress as DkmNativeInstructionAddress; if (nativeAddr == null) { var customAddr = frame.InstructionAddress as DkmCustomInstructionAddress; if (customAddr == null) { return; } var loc = new SourceLocation(customAddr.AdditionalData, thread.Process); nativeAddr = loc.NativeAddress; if (nativeAddr == null) { return; } } var bp = DkmRuntimeInstructionBreakpoint.Create(Guids.PythonStepTargetSourceGuid, thread, nativeAddr, false, null); bp.Enable(); _stepOutTargetBreakpoints.Add(bp); }
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); }
void IDkmLanguageExpressionEvaluator.GetFrameArguments(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmCompletionRoutine <DkmGetFrameArgumentsAsyncResult> completionRoutine) { throw new NotImplementedException(); }
void IDkmModuleSymbolsLoadedNotification.OnModuleSymbolsLoaded(DkmModuleInstance moduleInstance, DkmModule module, bool isReload, DkmWorkList workList, DkmEventDescriptor eventDescriptor) { var process = moduleInstance.Process; var engines = process.DebugLaunchSettings.EngineFilter; if (engines == null || !engines.Contains(AD7Engine.DebugEngineGuid)) { return; } var pyrtInfo = process.GetPythonRuntimeInfo(); var nativeModuleInstance = moduleInstance as DkmNativeModuleInstance; if (nativeModuleInstance != null) { if (PythonDLLs.CTypesNames.Contains(moduleInstance.Name)) { pyrtInfo.DLLs.CTypes = nativeModuleInstance; var traceHelper = process.GetDataItem <TraceManagerLocalHelper>(); if (traceHelper != null) { traceHelper.OnCTypesLoaded(nativeModuleInstance); } } else if (PythonDLLs.GetPythonLanguageVersion(nativeModuleInstance) != PythonLanguageVersion.None) { if (IsModuleCompiledWithPGO(moduleInstance)) { pyrtInfo.DLLs.Python = null; var pgoWarnMsg = DkmCustomMessage.Create(process.Connection, process, Guid.Empty, (int)VsPackageMessage.WarnAboutPGO, moduleInstance.Name, null); pgoWarnMsg.SendToVsService(Guids.CustomDebuggerEventHandlerGuid, IsBlocking: true); return; } } } if (process.GetPythonRuntimeInstance() != null) { return; } if (pyrtInfo.DLLs.Python != null && pyrtInfo.DLLs.Python.HasSymbols()) { if (process.LivePart == null || pyrtInfo.DLLs.DebuggerHelper != null) { CreatePythonRuntimeInstance(process); } else { InjectHelperDll(process); } } }
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); }
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; }); }
/// <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); }
private void GetEvaluationResultsAndContinue(ArrayBuilder <EvalResultDataItem> rows, DkmEvaluationResult[] results, int index, int numRows, DkmWorkList workList, DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, CompletionRoutine completionRoutine) { if (index >= numRows) { completionRoutine(); } else { CreateEvaluationResultAndContinue(rows[index], workList, inspectionContext, stackFrame, result => ContinueWithExceptionHandling( () => StoreResultAndContinue(result, rows, results, index, numRows, workList, inspectionContext, stackFrame, completionRoutine), e => { // If we fail to store a result, just stop enumerating rows (rather than attempting to store // an error message in the current row, etc). This is because it may have been the act of // indexing into the results store that threw (so it would just throw again here). The user // experience is less than ideal (there's no real indication that something went wrong), // however, it seems like it's better to enumerate/display some rows than none. We will // receive a non-fatal Watson report in this case, so the problem won't go unnoticed. completionRoutine(); })); } }
private void StoreResultAndContinue(DkmEvaluationResult result, ArrayBuilder <EvalResultDataItem> rows, DkmEvaluationResult[] results, int index, int numRows, DkmWorkList workList, DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, CompletionRoutine completionRoutine) { results[index] = result; index++; if (index < numRows) { GetEvaluationResultsAndContinue(rows, results, index, numRows, workList, inspectionContext, stackFrame, completionRoutine); } else { completionRoutine(); } }
private void GetRootResultAndContinue(DkmClrValue value, DkmWorkList workList, DkmClrType declaredType, DkmInspectionContext inspectionContext, string resultName, CompletionRoutine <DkmEvaluationResult> completionRoutine) { var type = value.Type.GetLmrType(); if (type.IsTypeVariables()) { var expansion = new TypeVariablesExpansion(type); var dataItem = new EvalResultDataItem( ExpansionKind.Default, resultName, typeDeclaringMember: null, declaredType: type, parent: null, value: value, displayValue: null, expansion: expansion, childShouldParenthesize: false, fullName: null, childFullNamePrefixOpt: null, formatSpecifiers: Formatter.NoFormatSpecifiers, category: DkmEvaluationResultCategory.Data, flags: DkmEvaluationResultFlags.ReadOnly, editableValue: null, inspectionContext: inspectionContext); Debug.Assert(dataItem.Flags == (DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable)); // Note: We're not including value.EvalFlags in Flags parameter // below (there shouldn't be a reason to do so). completionRoutine(DkmSuccessEvaluationResult.Create( InspectionContext: inspectionContext, StackFrame: value.StackFrame, Name: Resources.TypeVariablesName, FullName: dataItem.FullName, Flags: dataItem.Flags, Value: "", EditableValue: null, Type: "", Category: dataItem.Category, Access: value.Access, StorageType: value.StorageType, TypeModifierFlags: value.TypeModifierFlags, Address: value.Address, CustomUIVisualizers: null, ExternalModules: null, DataItem: dataItem)); } else { if ((inspectionContext.EvaluationFlags & DkmEvaluationFlags.ResultsOnly) != 0) { CreateEvaluationResultAndContinue( ResultsViewExpansion.CreateResultsOnlyRow(inspectionContext, resultName, declaredType, value, null, this.Formatter), workList, inspectionContext, value.StackFrame, completionRoutine); } else { ReadOnlyCollection <string> formatSpecifiers; var fullName = this.Formatter.TrimAndGetFormatSpecifiers(resultName, out formatSpecifiers); var dataItem = CreateDataItem( inspectionContext, resultName, typeDeclaringMember: null, declaredType: declaredType.GetLmrType(), value: value, parent: null, expansionFlags: ExpansionFlags.All, childShouldParenthesize: this.Formatter.NeedsParentheses(fullName), fullName: fullName, formatSpecifiers: formatSpecifiers, category: DkmEvaluationResultCategory.Other, flags: value.EvalFlags, evalFlags: inspectionContext.EvaluationFlags); GetResultAndContinue(dataItem, workList, declaredType, inspectionContext, parent: null, completionRoutine: completionRoutine); } } }
public virtual void GetItems(DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine<DkmEvaluationEnumAsyncResult> completionRoutine) { throw new NotImplementedException(); }