internal static DkmCompiledClrInspectionQuery ToQueryResult( this CompileResult compResult, DkmCompilerId languageId, ResultProperties resultProperties, DkmClrRuntimeInstance runtimeInstance) { if (compResult == null) { return(null); } Debug.Assert(compResult.Assembly != null); Debug.Assert(compResult.TypeName != null); Debug.Assert(compResult.MethodName != null); ReadOnlyCollection <byte> customTypeInfo; Guid customTypeInfoId = compResult.GetCustomTypeInfo(out customTypeInfo); return(DkmCompiledClrInspectionQuery.Create( runtimeInstance, Binary: new ReadOnlyCollection <byte>(compResult.Assembly), DataContainer: null, LanguageId: languageId, TypeName: compResult.TypeName, MethodName: compResult.MethodName, FormatSpecifiers: compResult.FormatSpecifiers, CompilationFlags: resultProperties.Flags, ResultCategory: resultProperties.Category, Access: resultProperties.AccessType, StorageType: resultProperties.StorageType, TypeModifierFlags: resultProperties.ModifierFlags, CustomTypeInfo: customTypeInfo.ToCustomTypeInfo(customTypeInfoId))); }
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; } }
/// <summary> /// This method is called by the debug engine to compile an expression that the user wants /// to evaluate. Before the call, we have the text of the expression and information about /// the context we want to evaluate in (code location, evaluation flags, etc.). The result /// of the call is a "query" containing IL the debugger will execute to get the /// result of the expression. /// </summary> /// <param name="expression">This is the raw expression to compile</param> /// <param name="instructionAddress">Instruction address or code location to use as the /// context of the compilation.</param> /// <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="error">[Out] If the there are any compile errors, this parameter is set to /// the error message to display to the user</param> /// <param name="result">[Out] If compilation was successful, this is the output query.</param> void IDkmClrExpressionCompiler.CompileExpression( DkmLanguageExpression expression, DkmClrInstructionAddress instructionAddress, DkmInspectionContext inspectionContext, out string error, out DkmCompiledClrInspectionQuery result) { error = null; result = null; using (DebugCompilerContext context = ContextFactory.CreateExpressionContext(inspectionContext, instructionAddress, expression.Text)) { context.GenerateQuery(); error = context.FirstError; if (string.IsNullOrEmpty(error)) { result = DkmCompiledClrInspectionQuery.Create( instructionAddress.RuntimeInstance, null, expression.Language.Id, new ReadOnlyCollection<byte>(context.GetPeBytes()), context.ClassName, context.MethodName, new ReadOnlyCollection<string>(context.FormatSpecifiers), context.ResultFlags, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.None, DkmEvaluationResultStorageType.None, DkmEvaluationResultTypeModifierFlags.None, null); } } }
/// <summary> /// This method is called by the debug engine to compile an expression that the user wants /// to evaluate. Before the call, we have the text of the expression and information about /// the context we want to evaluate in (code location, evaluation flags, etc.). The result /// of the call is a "query" containing IL the debugger will execute to get the /// result of the expression. /// </summary> /// <param name="expression">This is the raw expression to compile</param> /// <param name="instructionAddress">Instruction address or code location to use as the /// context of the compilation.</param> /// <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="error">[Out] If the there are any compile errors, this parameter is set to /// the error message to display to the user</param> /// <param name="result">[Out] If compilation was successful, this is the output query.</param> void IDkmClrExpressionCompiler.CompileExpression( DkmLanguageExpression expression, DkmClrInstructionAddress instructionAddress, DkmInspectionContext inspectionContext, out string error, out DkmCompiledClrInspectionQuery result) { error = null; result = null; using (DebugCompilerContext context = ContextFactory.CreateExpressionContext(inspectionContext, instructionAddress, expression.Text)) { context.GenerateQuery(); error = context.FirstError; if (string.IsNullOrEmpty(error)) { result = DkmCompiledClrInspectionQuery.Create( instructionAddress.RuntimeInstance, null, expression.Language.Id, new ReadOnlyCollection <byte>(context.GetPeBytes()), context.ClassName, context.MethodName, new ReadOnlyCollection <string>(context.FormatSpecifiers), context.ResultFlags, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.None, DkmEvaluationResultStorageType.None, DkmEvaluationResultTypeModifierFlags.None, null); } } }
/// <summary> /// This method is called by the debug engine to compile an expression that the user wants /// to evaluate. Before the call, we have the text of the expression and information about /// the context we want to evaluate in (code location, evaluation flags, etc.). The result /// of the call is a "query" containing IL the debugger will execute to get the /// result of the expression. /// </summary> /// <param name="expression">This is the raw expression to compile</param> /// <param name="instructionAddress">Instruction address or code location to use as the /// context of the compilation.</param> /// <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="error">[Out] If the there are any compile errors, this parameter is set to /// the error message to display to the user</param> /// <param name="result">[Out] If compilation was successful, this is the output query.</param> void IDkmClrExpressionCompiler.CompileExpression( DkmLanguageExpression expression, DkmClrInstructionAddress instructionAddress, DkmInspectionContext inspectionContext, out string error, out DkmCompiledClrInspectionQuery result) { error = null; result = null; expression.CompileExpression(instructionAddress, inspectionContext, out error, out result); return; }
/// <summary> /// This method is called by the debug engine to compile an expression that the user wants /// to evaluate. Before the call, we have the text of the expression and information about /// the context we want to evaluate in (code location, evaluation flags, etc.). The result /// of the call is a "query" containing IL the debugger will execute to get the /// result of the expression. /// </summary> /// <param name="expression">This is the raw expression to compile</param> /// <param name="instructionAddress">Instruction address or code location to use as the /// context of the compilation.</param> /// <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="error">[Out] If the there are any compile errors, this parameter is set to /// the error message to display to the user</param> /// <param name="result">[Out] If compilation was successful, this is the output query.</param> void IDkmClrExpressionCompiler.CompileExpression( DkmLanguageExpression expression, DkmClrInstructionAddress instructionAddress, DkmInspectionContext inspectionContext, out string error, out DkmCompiledClrInspectionQuery result) { error = null; result = null; bool changed = false; string originalExpr = expression.Text; // We use a trick to change the Text when sending it to C#, by retrieveing the field info. // This field has a property get but not a property set. var fi = typeof(DkmLanguageExpression).GetField("m_Text", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); if (fi != null) { var newexpr = originalExpr; if (expression.Text.StartsWith("SELF", System.StringComparison.OrdinalIgnoreCase)) { changed = true; newexpr = "this" + originalExpr.Substring(4); } else if (expression.Text.StartsWith("SUPER", System.StringComparison.OrdinalIgnoreCase)) { changed = true; newexpr = "base" + originalExpr.Substring(5); } if (newexpr.Contains(":")) { newexpr = newexpr.Replace(':', '.'); changed = true; } // check for literal array //var lbrkt = newexpr.IndexOf('['); //var rbrkt = newexpr.IndexOf(']'); //if (lbrkt > 0 && rbrkt > 0 && lbrkt < rbrkt) //{ // newexpr = AdjustArrayIndices(newexpr, ref changed); //} if (changed && fi != null) { fi.SetValue(expression, newexpr); } } expression.CompileExpression(instructionAddress, inspectionContext, out error, out result); if (changed && fi != null) { fi.SetValue(expression, originalExpr); } return; }
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; } }
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 appDomain = instructionAddress.ModuleInstance.AppDomain; var references = instructionAddress.Process.GetMetadataBlocks(appDomain); ImmutableArray<AssemblyIdentity> missingAssemblyIdentities; ResultProperties resultProperties; CompileResult compileResult; do { var context = this.CreateMethodContext(instructionAddress, references); compileResult = context.CompileExpression( RuntimeInspectionContext.Create(inspectionContext), expression.Text, expression.CompilationFlags, this.DiagnosticFormatter, out resultProperties, out error, out missingAssemblyIdentities, preferredUICulture: null, testData: null); } while (ShouldTryAgainWithMoreMetadataBlocks(appDomain, missingAssemblyIdentities, ref references)); result = compileResult.ToQueryResult(this.CompilerId, resultProperties, instructionAddress.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; } }
/// <summary> /// This method is called by the debug engine when the user modifies the result of a /// previous evaluation. The result of this call will be a query containing the IL code /// necessary to assign the value. /// </summary> /// <param name="expression">The text the user entered as the new value</param> /// <param name="instructionAddress">Instruction address or code location to use as the /// context of the compilation.</param> /// <param name="lValue">The L-Value of the assigment. This is a previous evaluation result.</param> /// <param name="error">[Out] If the there are any compile errors, this parameter is set to /// the error message to display to the user</param> /// <param name="result">[Out] If compilation was successful, this is the output query to /// execute to perform the assignment.</param> void IDkmClrExpressionCompiler.CompileAssignment(DkmLanguageExpression expression, DkmClrInstructionAddress instructionAddress, DkmEvaluationResult lValue, out string error, out DkmCompiledClrInspectionQuery result) { // when the user assigns a value in the debugger then this method is called. // we may want to change an expression like "{1,2,3}" to "new object[] {1,2,3}" // and "2020.12.03" to "XSharp.RT.Functions.ConDate(2020,12,03)" error = null; result = null; expression.CompileAssignment(instructionAddress, lValue, out error, out result); }
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; } }
/// <summary> /// This method is called by the debug engine when the user modifies the result of a /// previous evaluation. The result of this call will be a query containing the IL code /// necessary to assign the value. /// </summary> /// <param name="expression">The text the user entered as the new value</param> /// <param name="instructionAddress">Instruction address or code location to use as the /// context of the compilation.</param> /// <param name="lValue">The L-Value of the assigment. This is a previous evaluation result.</param> /// <param name="error">[Out] If the there are any compile errors, this parameter is set to /// the error message to display to the user</param> /// <param name="result">[Out] If compilation was successful, this is the output query to /// execute to perform the assignment.</param> void IDkmClrExpressionCompiler.CompileAssignment(DkmLanguageExpression expression, DkmClrInstructionAddress instructionAddress, DkmEvaluationResult lValue, out string error, out DkmCompiledClrInspectionQuery result) { error = null; result = null; expression.CompileAssignment(instructionAddress, lValue, out error, out result); }