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; } }
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); } }
void IDkmClrExpressionCompilerCallback.CompileDisplayAttribute( DkmLanguageExpression expression, DkmClrModuleInstance moduleInstance, int token, out string error, out DkmCompiledClrInspectionQuery result) { try { var runtimeInstance = moduleInstance.RuntimeInstance; var appDomain = moduleInstance.AppDomain; var compileResult = this.CompileWithRetry( moduleInstance, runtimeInstance.GetMetadataBlocks(appDomain), (blocks, useReferencedModulesOnly) => CreateTypeContext(appDomain, blocks, moduleInstance.Mvid, token, useReferencedModulesOnly), (context, diagnostics) => { ResultProperties unusedResultProperties; return(context.CompileExpression( RuntimeInspectionContext.Empty, expression.Text, DkmEvaluationFlags.TreatAsExpression, diagnostics, out unusedResultProperties, testData: null)); }, out error); result = compileResult.ToQueryResult(this.CompilerId, default(ResultProperties), runtimeInstance); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
DkmCompiledClrLocalsQuery IDkmClrExpressionCompiler.GetClrLocalVariableQuery( DkmInspectionContext inspectionContext, DkmClrInstructionAddress instructionAddress, bool argumentsOnly) { try { var references = instructionAddress.Process.GetMetadataBlocks(instructionAddress.ModuleInstance.AppDomain); var context = this.CreateMethodContext(instructionAddress, references); var builder = ArrayBuilder <LocalAndMethod> .GetInstance(); string typeName; var assembly = context.CompileGetLocals( builder, argumentsOnly, out typeName, testData: null); Debug.Assert((builder.Count == 0) == (assembly.Count == 0)); var locals = new ReadOnlyCollection <DkmClrLocalVariableInfo>(builder.SelectAsArray(l => DkmClrLocalVariableInfo.Create(l.LocalName, l.MethodName, l.Flags, DkmEvaluationResultCategory.Data))); builder.Free(); return(DkmCompiledClrLocalsQuery.Create(inspectionContext.RuntimeInstance, null, this.CompilerId, assembly, typeName, locals)); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
string IDkmLanguageInstructionDecoder.GetMethodName(DkmLanguageInstructionAddress languageInstructionAddress, DkmVariableInfoFlags argumentFlags) { try { // DkmVariableInfoFlags.FullNames was accepted by the old GetMethodName implementation, // but it was ignored. Furthermore, it's not clear what FullNames would mean with respect // to argument names in C# or Visual Basic. For consistency with the old behavior, we'll // just ignore the flag as well. Debug.Assert((argumentFlags & (DkmVariableInfoFlags.FullNames | DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types)) == argumentFlags, $"Unexpected argumentFlags '{argumentFlags}'"); var instructionAddress = (DkmClrInstructionAddress)languageInstructionAddress.Address; var compilation = _instructionDecoder.GetCompilation(instructionAddress.ModuleInstance); var method = _instructionDecoder.GetMethod(compilation, instructionAddress); var includeParameterTypes = argumentFlags.Includes(DkmVariableInfoFlags.Types); var includeParameterNames = argumentFlags.Includes(DkmVariableInfoFlags.Names); return(_instructionDecoder.GetName(method, includeParameterTypes, includeParameterNames)); } catch (NotImplementedMetadataException) { return(languageInstructionAddress.GetMethodName(argumentFlags)); } 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; } }
internal static void ContinueWithExceptionHandling(CompletionRoutine onCompleted, CompletionRoutine <Exception> onException) { try { onCompleted(); } catch (Exception e) when(ExpressionEvaluatorFatalError.ReportNonFatalException(e, DkmComponentManager.ReportCurrentNonFatalException)) { onException(e); } }
internal DkmEvaluationResult GetResult(DkmClrValue value, DkmClrType declaredType, ReadOnlyCollection <string> formatSpecifiers, string resultName, string resultFullName) { // TODO: Use full name try { return(GetRootResult(value, declaredType, resultName)); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
void IDkmLanguageFrameDecoder.GetFrameReturnType(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmCompletionRoutine <DkmGetFrameReturnTypeAsyncResult> completionRoutine) { try { var returnType = _instructionDecoder.GetReturnType((DkmClrInstructionAddress)frame.InstructionAddress); var result = new DkmGetFrameReturnTypeAsyncResult(returnType); completionRoutine(result); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
internal void Execute() { while (_completionRoutine != null) { var completionRoutine = _completionRoutine; _completionRoutine = null; try { completionRoutine(); } catch (Exception e) when(ExpressionEvaluatorFatalError.ReportNonFatalException(e, DkmComponentManager.ReportCurrentNonFatalException)) { _onException(e); } } }
DkmClrValue IDkmClrResultProvider.GetClrValue(DkmSuccessEvaluationResult evaluationResult) { try { var dataItem = evaluationResult.GetDataItem <EvalResultDataItem>(); if (dataItem == null) { return(null); } return(dataItem.Value); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
DkmClrValue IDkmClrResultProvider.GetClrValue(DkmSuccessEvaluationResult evaluationResult) { try { var dataItem = evaluationResult.GetDataItem <EvalResultDataItem>(); if (dataItem == null) { // We don't know about this result. Call next implementation return(evaluationResult.GetClrValue()); } return(dataItem.Value); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
string IDkmClrResultProvider.GetUnderlyingString(DkmEvaluationResult result) { try { var dataItem = result.GetDataItem <EvalResultDataItem>(); if (dataItem == null) { // We don't know about this result. Call next implementation return(result.GetUnderlyingString()); } return(dataItem.Value?.GetUnderlyingString(result.InspectionContext)); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
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) when(ExpressionEvaluatorFatalError.ReportNonFatalException(e, DkmComponentManager.ReportCurrentNonFatalException)) { onFailure(e); } }); } else { onSuccess(method); } }
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; } }
void IDkmClrExpressionCompiler.CompileAssignment( DkmLanguageExpression expression, DkmClrInstructionAddress instructionAddress, DkmEvaluationResult lValue, out string error, out DkmCompiledClrInspectionQuery result) { try { var moduleInstance = instructionAddress.ModuleInstance; var runtimeInstance = instructionAddress.RuntimeInstance; var aliases = GetAliases(runtimeInstance, lValue.InspectionContext); // NB: Not affected by retrying. var r = this.CompileWithRetry( moduleInstance.AppDomain, runtimeInstance, (blocks, useReferencedModulesOnly) => CreateMethodContext(instructionAddress, blocks, useReferencedModulesOnly), (context, diagnostics) => { ResultProperties resultProperties; var compileResult = context.CompileAssignment( lValue.FullName, expression.Text, aliases, diagnostics, out resultProperties, testData: null); return(new CompileExpressionResult(compileResult, resultProperties)); }, out error); Debug.Assert( r.CompileResult == null && r.ResultProperties.Flags == default || (r.ResultProperties.Flags & DkmClrCompilationResultFlags.PotentialSideEffect) == DkmClrCompilationResultFlags.PotentialSideEffect); result = r.CompileResult.ToQueryResult(this.CompilerId, r.ResultProperties, runtimeInstance); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
DkmCompiledClrLocalsQuery IDkmClrExpressionCompiler.GetClrLocalVariableQuery( DkmInspectionContext inspectionContext, DkmClrInstructionAddress instructionAddress, bool argumentsOnly) { try { var moduleInstance = instructionAddress.ModuleInstance; var runtimeInstance = instructionAddress.RuntimeInstance; var aliases = argumentsOnly ? ImmutableArray <Alias> .Empty : GetAliases(runtimeInstance, inspectionContext); // NB: Not affected by retrying. string error; var r = this.CompileWithRetry( moduleInstance, runtimeInstance.GetMetadataBlocks(moduleInstance.AppDomain), (blocks, useReferencedModulesOnly) => CreateMethodContext(instructionAddress, blocks, useReferencedModulesOnly), (context, diagnostics) => { var builder = ArrayBuilder <LocalAndMethod> .GetInstance(); string typeName; var assembly = context.CompileGetLocals( builder, argumentsOnly, aliases, diagnostics, out typeName, testData: null); Debug.Assert((builder.Count == 0) == (assembly.Count == 0)); var locals = new ReadOnlyCollection <DkmClrLocalVariableInfo>(builder.SelectAsArray(ToLocalVariableInfo)); builder.Free(); return(new GetLocalsResult(typeName, locals, assembly)); }, out error); return(DkmCompiledClrLocalsQuery.Create(runtimeInstance, null, this.CompilerId, r.Assembly, r.TypeName, r.Locals)); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
void IDkmClrExpressionCompiler.CompileAssignment( DkmLanguageExpression expression, DkmClrInstructionAddress instructionAddress, DkmEvaluationResult lValue, out string error, out DkmCompiledClrInspectionQuery result) { try { var appDomain = instructionAddress.ModuleInstance.AppDomain; var references = instructionAddress.Process.GetMetadataBlocks(appDomain); ResultProperties resultProperties; ImmutableArray <AssemblyIdentity> missingAssemblyIdentities; CompileResult compileResult; do { var context = this.CreateMethodContext(instructionAddress, references); compileResult = context.CompileAssignment( RuntimeInspectionContext.Create(lValue.InspectionContext), lValue.FullName, expression.Text, this.DiagnosticFormatter, out resultProperties, out error, out missingAssemblyIdentities, preferredUICulture: null, testData: null); } while (ShouldTryAgainWithMoreMetadataBlocks(appDomain, missingAssemblyIdentities, ref references)); Debug.Assert((resultProperties.Flags & DkmClrCompilationResultFlags.PotentialSideEffect) == DkmClrCompilationResultFlags.PotentialSideEffect); result = compileResult.ToQueryResult(this.CompilerId, resultProperties, instructionAddress.RuntimeInstance); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
void IDkmClrExpressionCompilerCallback.CompileDisplayAttribute( DkmLanguageExpression expression, DkmClrModuleInstance moduleInstance, int token, out string error, out DkmCompiledClrInspectionQuery result) { try { var appDomain = moduleInstance.AppDomain; var references = moduleInstance.Process.GetMetadataBlocks(appDomain); ResultProperties unusedResultProperties; ImmutableArray <AssemblyIdentity> missingAssemblyIdentities; CompileResult compileResult; do { var context = this.CreateTypeContext(moduleInstance, references, token); compileResult = context.CompileExpression( RuntimeInspectionContext.Empty, expression.Text, DkmEvaluationFlags.TreatAsExpression, this.DiagnosticFormatter, out unusedResultProperties, out error, out missingAssemblyIdentities, preferredUICulture: null, testData: null); } while (ShouldTryAgainWithMoreMetadataBlocks(appDomain, missingAssemblyIdentities, ref references)); result = compileResult.ToQueryResult(this.CompilerId, default(ResultProperties), moduleInstance.RuntimeInstance); } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
void IDkmClrExpressionCompiler.CompileExpression( DkmLanguageExpression expression, DkmClrInstructionAddress instructionAddress, DkmInspectionContext inspectionContext, out string error, out DkmCompiledClrInspectionQuery result) { try { var moduleInstance = instructionAddress.ModuleInstance; var runtimeInstance = instructionAddress.RuntimeInstance; var runtimeInspectionContext = RuntimeInspectionContext.Create(inspectionContext); var r = this.CompileWithRetry( moduleInstance, runtimeInstance.GetMetadataBlocks(moduleInstance.AppDomain), (blocks, useReferencedModulesOnly) => CreateMethodContext(instructionAddress, blocks, useReferencedModulesOnly), (context, diagnostics) => { ResultProperties resultProperties; var compileResult = context.CompileExpression( runtimeInspectionContext, expression.Text, expression.CompilationFlags, diagnostics, out resultProperties, testData: null); return(new CompileExpressionResult(compileResult, resultProperties)); }, out error); result = r.CompileResult.ToQueryResult(this.CompilerId, r.ResultProperties, runtimeInstance); } 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 = {0}", argumentFlags); var instructionAddress = (DkmClrInstructionAddress)frame.InstructionAddress; 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 => { try { var builder = ArrayBuilder <string> .GetInstance(); foreach (var argument in result.Arguments) { var evaluatedArgument = argument as DkmSuccessEvaluationResult; // Not expecting Expandable bit, at least not from this EE. Debug.Assert((evaluatedArgument == null) || (evaluatedArgument.Flags & DkmEvaluationResultFlags.Expandable) == 0); builder.Add((evaluatedArgument != null) ? evaluatedArgument.Value : null); } var frameName = _instructionDecoder.GetName(instructionAddress, includeParameterTypes, includeParameterNames, builder); builder.Free(); completionRoutine(new DkmGetFrameNameAsyncResult(frameName)); } // TODO: Consider calling DkmComponentManager.ReportCurrentNonFatalException() to // trigger a non-fatal Watson when this occurs. catch (Exception e) when(!ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { completionRoutine(DkmGetFrameNameAsyncResult.CreateErrorResult(e)); } finally { foreach (var argument in result.Arguments) { argument.Close(); } } }); } else { var frameName = _instructionDecoder.GetName(instructionAddress, includeParameterTypes, includeParameterNames, null); completionRoutine(new DkmGetFrameNameAsyncResult(frameName)); } } catch (Exception e) when(ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
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)); } }