public InspectionScope(DkmClrInstructionAddress address, InspectionSession session) { InstructionAddress = address; SymModule = address.ModuleInstance.Module; CurrentMethodToken = address.MethodId.Token; Session = session; }
private EvaluationContextBase CreateMethodContext(DkmClrInstructionAddress instructionAddress, ImmutableArray <MetadataBlock> metadataBlocks) { var moduleInstance = instructionAddress.ModuleInstance; var methodToken = instructionAddress.MethodId.Token; int localSignatureToken; try { localSignatureToken = moduleInstance.GetLocalSignatureToken(methodToken); } catch (InvalidOperationException) { // No local signature. May occur when debugging .dmp. localSignatureToken = 0; } catch (FileNotFoundException) { // No local signature. May occur when debugging heapless dumps. localSignatureToken = 0; } return(this.CreateMethodContext( moduleInstance.AppDomain, metadataBlocks, new Lazy <ImmutableArray <AssemblyReaders> >(() => instructionAddress.MakeAssemblyReaders(), LazyThreadSafetyMode.None), symReader: moduleInstance.GetSymReader(), moduleVersionId: moduleInstance.Mvid, methodToken: methodToken, methodVersion: (int)instructionAddress.MethodId.Version, ilOffset: (int)instructionAddress.ILOffset, localSignatureToken: localSignatureToken)); }
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; } }
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 = CompileWithRetry( moduleInstance.AppDomain, runtimeInstance, (blocks, useReferencedModulesOnly) => CreateMethodContext(instructionAddress, blocks, useReferencedModulesOnly), (context, diagnostics) => { var builder = ArrayBuilder <LocalAndMethod> .GetInstance(); var assembly = context.CompileGetLocals( builder, argumentsOnly, aliases, diagnostics, out var 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, CompilerId, r.Assembly, r.TypeName, r.Locals)); }
internal static ImmutableArray <AssemblyReaders> MakeAssemblyReaders(this DkmClrInstructionAddress instructionAddress) { var builder = ArrayBuilder <AssemblyReaders> .GetInstance(); foreach (DkmClrModuleInstance module in instructionAddress.RuntimeInstance.GetModulesInAppDomain(instructionAddress.ModuleInstance.AppDomain)) { var symReader = module.GetSymReader(); if (symReader == null) { continue; } MetadataReader reader; unsafe { try { uint size; IntPtr ptr; ptr = module.GetMetaDataBytesPtr(out size); Debug.Assert(size > 0); reader = new MetadataReader((byte *)ptr, (int)size); } catch (Exception e) when(MetadataUtilities.IsBadOrMissingMetadataException(e, module.FullName)) { continue; } } builder.Add(new AssemblyReaders(reader, symReader)); } return(builder.ToImmutableAndFree()); }
/// <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); } } }
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; } }
/// <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; }
internal override MethodSymbol GetMethod( CSharpCompilation compilation, DkmClrInstructionAddress instructionAddress ) { var methodHandle = (MethodDefinitionHandle)MetadataTokens.Handle( instructionAddress.MethodId.Token ); return(compilation.GetSourceMethod( instructionAddress.ModuleInstance.Mvid, methodHandle )); }
public InspectionScope GetScope(DkmClrInstructionAddress address) { // Cache the various scopes used during the inspection session. Different scopes are // used when the user selects different frames and when the debug engine asks us to // format each stack frame. InspectionScope scope; if (!_scopes.TryGetValue(address, out scope)) { scope = new InspectionScope(address, this); _scopes.Add(address, scope); } return scope; }
public InspectionScope GetScope(DkmClrInstructionAddress address) { // Cache the various scopes used during the inspection session. Different scopes are // used when the user selects different frames and when the debug engine asks us to // format each stack frame. InspectionScope scope; if (!_scopes.TryGetValue(address, out scope)) { scope = new InspectionScope(address, this); _scopes.Add(address, scope); } return(scope); }
internal override void OnFunctionResolved( 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); request.OnFunctionResolved(address); }
internal static ImmutableArray <AssemblyReaders> MakeAssemblyReaders(this DkmClrInstructionAddress instructionAddress) { var builder = ArrayBuilder <AssemblyReaders> .GetInstance(); foreach (DkmClrModuleInstance module in instructionAddress.Process.GetModulesInAppDomain(instructionAddress.ModuleInstance.AppDomain)) { MetadataReader metadataReader; if (module.TryGetMetadataReader(out metadataReader)) { var symReader = module.GetSymReader(); if (symReader != null) { builder.Add(new AssemblyReaders(metadataReader, symReader)); } } } return(builder.ToImmutableAndFree()); }
private static OnFunctionResolvedDelegate <DkmClrModuleInstance, DkmRuntimeFunctionResolutionRequest> 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: 0, ILOffset: (uint)ilOffset, CPUInstruction: null); // Use async overload of OnFunctionResolved to avoid deadlock. request.OnFunctionResolved(workList, address, result => { }); }); }
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 runtimeInspectionContext = RuntimeInspectionContext.Create(inspectionContext); var aliases = argumentsOnly ? null : s_NoAliases; 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( aliases, builder, argumentsOnly, 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; } }
internal override CSharpCompilation GetCompilation(DkmClrInstructionAddress instructionAddress) { var moduleInstance = instructionAddress.ModuleInstance; var appDomain = moduleInstance.AppDomain; var previous = appDomain.GetDataItem <CSharpMetadataContext>(); var metadataBlocks = instructionAddress.Process.GetMetadataBlocks(appDomain); CSharpCompilation compilation; if (metadataBlocks.HaveNotChanged(previous)) { compilation = previous.Compilation; } else { var dataItem = new CSharpMetadataContext(metadataBlocks); appDomain.SetDataItem(DkmDataCreationDisposition.CreateAlways, dataItem); compilation = dataItem.Compilation; } return(compilation); }
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; } }
public static DebugCompilerContext CreateLocalsContext(DkmInspectionContext inspectionContext, DkmClrInstructionAddress address, bool argumentsOnly) { MemoryStream input; StreamReader reader; CreateInputStream(string.Empty, out input, out reader); InspectionSession session = InspectionSession.GetInstance(inspectionContext.InspectionSession); InspectionScope scope = session.GetScope(address); DebugCompilerContext context = new DebugCompilerContext( null /* null because the context doesn't own the lifetime of the session */, scope, input, reader, typeof(LocalVariablesTranslator), null /* Method name is not applicable because we create multiple methods for Locals. */, new List<DkmClrLocalVariableInfo>(), null /* Assignment L-Value only applies to assigments */, argumentsOnly); context.InitializeSymbols(); return context; }
public static DebugCompilerContext CreateAssignmentContext(DkmEvaluationResult lValue, DkmClrInstructionAddress address, string expression) { MemoryStream input; StreamReader reader; CreateInputStream(expression, out input, out reader); InspectionSession session = InspectionSession.GetInstance(lValue.InspectionSession); InspectionScope scope = session.GetScope(address); DebugCompilerContext context = new DebugCompilerContext( null /* null because the context doesn't own the lifetime of the session */, scope, input, reader, typeof(AssignmentTranslator), "$.M1", null /* Generated locals is not applicable for assigments */, lValue.FullName, false /* "ArgumentsOnly" only applies to local variable query */); context.InitializeSymbols(); return context; }
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; } }
public static DebugCompilerContext CreateExpressionContext(DkmInspectionContext inspectionContext, DkmClrInstructionAddress address, string expression) { InspectionSession ownedSession = null; InspectionScope scope; if (inspectionContext != null) { InspectionSession session = InspectionSession.GetInstance(inspectionContext.InspectionSession); scope = session.GetScope(address); } else { // There is no inspection context when compiling breakpoint conditions. Create a // new temporary session. The context will need to dispose of this new session // when it is disposed. ownedSession = new InspectionSession(); scope = ownedSession.GetScope(address); } MemoryStream input; StreamReader reader; CreateInputStream(expression, out input, out reader); DebugCompilerContext context = new DebugCompilerContext( ownedSession, scope, input, reader, typeof(ExpressionTranslator), "$.M1", null /* Generated locals is not applicable for compiling expressions */, null /* Assignment L-Value only applies to assigments */, false /* "ArgumentsOnly" only applies to local variable query */); context.InitializeSymbols(); return context; }
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; } }
internal override MethodSymbol GetMethod(CSharpCompilation compilation, DkmClrInstructionAddress instructionAddress) { return(compilation.GetSourceMethod(instructionAddress.ModuleInstance.Mvid, instructionAddress.MethodId.Token)); }
/// <summary> /// This method is called by the debug engine to retrieve the current local variables. /// The result of this call will be a query containing the names of the local variables /// as well as IL code to retrieve each variable value. /// </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="instructionAddress">Instruction address or code location to use as the /// reference point for where we need to retrieve the local variables</param> /// <param name="argumentsOnly">True if only arguments are needed</param> /// <returns>A local variables query</returns> DkmCompiledClrLocalsQuery IDkmClrExpressionCompiler.GetClrLocalVariableQuery(DkmInspectionContext inspectionContext, DkmClrInstructionAddress instructionAddress, bool argumentsOnly) { using (DebugCompilerContext context = ContextFactory.CreateLocalsContext(inspectionContext, instructionAddress, argumentsOnly)) { context.GenerateQuery(); return DkmCompiledClrLocalsQuery.Create( inspectionContext.RuntimeInstance, null, inspectionContext.Language.Id, new ReadOnlyCollection<byte>(context.GetPeBytes()), context.ClassName, new ReadOnlyCollection<DkmClrLocalVariableInfo>(context.GeneratedLocals)); } }
internal abstract string GetName(DkmClrInstructionAddress instructionAddress, bool includeParameterTypes, bool includeParameterNames, ArrayBuilder <string> argumentValues);
internal abstract string GetReturnType(DkmClrInstructionAddress instructionAddress);
internal abstract TCompilation GetCompilation(DkmClrInstructionAddress instructionAddress);
/// <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); }
public static DebugCompilerContext CreateLocalsContext(DkmInspectionContext inspectionContext, DkmClrInstructionAddress address, bool argumentsOnly) { MemoryStream input; StreamReader reader; CreateInputStream(string.Empty, out input, out reader); InspectionSession session = InspectionSession.GetInstance(inspectionContext.InspectionSession); InspectionScope scope = session.GetScope(address); DebugCompilerContext context = new DebugCompilerContext( null /* null because the context doesn't own the lifetime of the session */, scope, input, reader, typeof(LocalVariablesTranslator), null /* Method name is not applicable because we create multiple methods for Locals. */, new List <DkmClrLocalVariableInfo>(), null /* Assignment L-Value only applies to assigments */, argumentsOnly); context.InitializeSymbols(); return(context); }
public static DebugCompilerContext CreateAssignmentContext(DkmEvaluationResult lValue, DkmClrInstructionAddress address, string expression) { MemoryStream input; StreamReader reader; CreateInputStream(expression, out input, out reader); InspectionSession session = InspectionSession.GetInstance(lValue.InspectionSession); InspectionScope scope = session.GetScope(address); DebugCompilerContext context = new DebugCompilerContext( null /* null because the context doesn't own the lifetime of the session */, scope, input, reader, typeof(AssignmentTranslator), "$.M1", null /* Generated locals is not applicable for assigments */, lValue.FullName, false /* "ArgumentsOnly" only applies to local variable query */); context.InitializeSymbols(); return(context); }
public static DebugCompilerContext CreateExpressionContext(DkmInspectionContext inspectionContext, DkmClrInstructionAddress address, string expression) { InspectionSession ownedSession = null; InspectionScope scope; if (inspectionContext != null) { InspectionSession session = InspectionSession.GetInstance(inspectionContext.InspectionSession); scope = session.GetScope(address); } else { // There is no inspection context when compiling breakpoint conditions. Create a // new temporary session. The context will need to dispose of this new session // when it is disposed. ownedSession = new InspectionSession(); scope = ownedSession.GetScope(address); } MemoryStream input; StreamReader reader; CreateInputStream(expression, out input, out reader); DebugCompilerContext context = new DebugCompilerContext( ownedSession, scope, input, reader, typeof(ExpressionTranslator), "$.M1", null /* Generated locals is not applicable for compiling expressions */, null /* Assignment L-Value only applies to assigments */, false /* "ArgumentsOnly" only applies to local variable query */); context.InitializeSymbols(); return(context); }
private EvaluationContextBase CreateMethodContext(DkmClrInstructionAddress instructionAddress, ImmutableArray<MetadataBlock> metadataBlocks) { var moduleInstance = instructionAddress.ModuleInstance; var methodToken = instructionAddress.MethodId.Token; int localSignatureToken; try { localSignatureToken = moduleInstance.GetLocalSignatureToken(methodToken); } catch (InvalidOperationException) { // No local signature. May occur when debugging .dmp. localSignatureToken = 0; } catch (FileNotFoundException) { // No local signature. May occur when debugging heapless dumps. localSignatureToken = 0; } return this.CreateMethodContext( moduleInstance.AppDomain, metadataBlocks, new Lazy<ImmutableArray<AssemblyReaders>>(() => instructionAddress.MakeAssemblyReaders(), LazyThreadSafetyMode.None), symReader: moduleInstance.GetSymReader(), moduleVersionId: moduleInstance.Mvid, methodToken: methodToken, methodVersion: (int)instructionAddress.MethodId.Version, ilOffset: (int)instructionAddress.ILOffset, localSignatureToken: localSignatureToken); }
/// <summary> /// This method is called by the debug engine to retrieve the current local variables. /// The result of this call will be a query containing the names of the local variables /// as well as IL code to retrieve each variable value. /// </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="instructionAddress">Instruction address or code location to use as the /// reference point for where we need to retrieve the local variables</param> /// <param name="argumentsOnly">True if only arguments are needed</param> /// <returns>A local variables query</returns> DkmCompiledClrLocalsQuery IDkmClrExpressionCompiler.GetClrLocalVariableQuery(DkmInspectionContext inspectionContext, DkmClrInstructionAddress instructionAddress, bool argumentsOnly) { var result = inspectionContext.GetClrLocalVariableQuery(instructionAddress, argumentsOnly); var newlocals = new List <DkmClrLocalVariableInfo>(); bool changed = false; foreach (var loc in result.LocalInfo) { if (loc.VariableName.Contains("$")) { // do not add changed = true; } else if (loc.VariableName == "this") { // rename var newloc = DkmClrLocalVariableInfo.Create("SELF", "SELF", loc.MethodName, loc.CompilationFlags, loc.ResultCategory, loc.CustomTypeInfo); newlocals.Add(newloc); changed = true; } else { newlocals.Add(loc); } } if (changed) { result = DkmCompiledClrLocalsQuery.Create(result.RuntimeInstance, result.DataContainer, result.LanguageId, result.Binary, result.TypeName, new ReadOnlyCollection <DkmClrLocalVariableInfo>(newlocals)); } return(result); }
/// <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); }
/// <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; using (DebugCompilerContext context = ContextFactory.CreateAssignmentContext(lValue, 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), DkmClrCompilationResultFlags.None, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.None, DkmEvaluationResultStorageType.None, DkmEvaluationResultTypeModifierFlags.None, null); } } }
internal abstract TMethodSymbol GetMethod(TCompilation compilation, DkmClrInstructionAddress instructionAddress);
/// <summary> /// This method is called by the debug engine to retrieve the current local variables. /// The result of this call will be a query containing the names of the local variables /// as well as IL code to retrieve each variable value. /// </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="instructionAddress">Instruction address or code location to use as the /// reference point for where we need to retrieve the local variables</param> /// <param name="argumentsOnly">True if only arguments are needed</param> /// <returns>A local variables query</returns> DkmCompiledClrLocalsQuery IDkmClrExpressionCompiler.GetClrLocalVariableQuery(DkmInspectionContext inspectionContext, DkmClrInstructionAddress instructionAddress, bool argumentsOnly) { using (DebugCompilerContext context = ContextFactory.CreateLocalsContext(inspectionContext, instructionAddress, argumentsOnly)) { context.GenerateQuery(); return(DkmCompiledClrLocalsQuery.Create( inspectionContext.RuntimeInstance, null, inspectionContext.Language.Id, new ReadOnlyCollection <byte>(context.GetPeBytes()), context.ClassName, new ReadOnlyCollection <DkmClrLocalVariableInfo>(context.GeneratedLocals))); } }