public abstract DbgEngineValueNode CreateTypeVariables(DbgEvaluationContext context, DbgStackFrame frame, DbgDotNetTypeVariableInfo[] typeVariableInfos, CancellationToken cancellationToken);
public override ValueNodesProviderResult GetNodes(DbgEvaluationContext context, DbgLanguage language, DbgStackFrame frame, DbgEvaluationOptions evalOptions, DbgValueNodeEvaluationOptions nodeEvalOptions) { var recreateAllNodes = forceRecreateAllNodesl; forceRecreateAllNodesl = false; var cancellationToken = CancellationToken.None; const CultureInfo cultureInfo = null; var exceptions = language.ExceptionsProvider.GetNodes(context, frame, nodeEvalOptions, cancellationToken); var returnValues = language.ReturnValuesProvider.GetNodes(context, frame, nodeEvalOptions, cancellationToken); var variables = language.LocalsProvider.GetNodes(context, frame, nodeEvalOptions, GetLocalsValueNodeOptions(), cancellationToken); var typeVariables = language.TypeVariablesProvider.GetNodes(context, frame, nodeEvalOptions, cancellationToken); var objectIds = dbgObjectIdService.GetObjectIds(frame.Runtime); Array.Sort(objectIds, DbgObjectIdComparer.Instance); int count = exceptions.Length + returnValues.Length + objectIds.Length + variables.Length + typeVariables.Length; if (count == 0) { return(new ValueNodesProviderResult(Array.Empty <DbgValueNodeInfo>(), false)); } var res = new DbgValueNodeInfo[count]; int ri = 0; for (int i = 0; i < exceptions.Length; i++, ri++) { ulong id = (uint)i; var exception = exceptions[i]; if (exception.ImageName == PredefinedDbgValueNodeImageNames.StowedException) { id |= 1UL << 32; } res[ri] = new DbgValueNodeInfo(exception, GetNextExceptionId(id), causesSideEffects: false); } for (int i = 0; i < returnValues.Length; i++, ri++) { res[ri] = new DbgValueNodeInfo(returnValues[i], GetNextReturnValueId(), causesSideEffects: false); } var objectIdNodes = language.ValueNodeFactory.Create(context, frame, objectIds, nodeEvalOptions); Debug.Assert(objectIdNodes.Length == objectIds.Length); for (int i = 0; i < objectIdNodes.Length; i++, ri++) { var id = GetObjectIdNodeId(objectIds[i]); res[ri] = new DbgValueNodeInfo(objectIdNodes[i], id, causesSideEffects: false); } variables = GetSortedVariables(context, frame, variables, cultureInfo, cancellationToken); for (int i = 0; i < variables.Length; i++, ri++) { res[ri] = new DbgValueNodeInfo(variables[i].ValueNode, causesSideEffects: false); } for (int i = 0; i < typeVariables.Length; i++, ri++) { res[ri] = new DbgValueNodeInfo(typeVariables[i], GetNextTypeVariableId((uint)i), causesSideEffects: false); } if (res.Length != ri) { throw new InvalidOperationException(); } return(new ValueNodesProviderResult(res, recreateAllNodes)); }
string GetName(DbgEvaluationContext context, DbgStackFrame frame, StringBuilderTextColorOutput output, DbgValueNode valueNode, CultureInfo cultureInfo, CancellationToken cancellationToken) { output.Reset(); valueNode.FormatName(context, frame, output, cultureInfo, cancellationToken); return(output.ToString()); }
public override DbgLocalsValueNodeInfo[] GetNodes(DbgEvaluationContext context, DbgStackFrame frame, DbgValueNodeEvaluationOptions options, DbgLocalsValueNodeEvaluationOptions localsOptions, CancellationToken cancellationToken) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (!(context is DbgEvaluationContextImpl)) { throw new ArgumentException(); } if (context.Language != Language) { throw new ArgumentException(); } if (context.Runtime.RuntimeKindGuid != runtimeKindGuid) { throw new ArgumentException(); } if (frame == null) { throw new ArgumentNullException(nameof(frame)); } if (frame.Runtime.RuntimeKindGuid != runtimeKindGuid) { throw new ArgumentException(); } return(DbgValueNodeUtils.ToLocalsValueNodeInfoArray(Language, frame.Runtime, engineLocalsValueNodeProvider.GetNodes(context, frame, options, localsOptions, cancellationToken))); }
/// <summary> /// Compiles an assignment /// </summary> /// <param name="context">Evaluation context</param> /// <param name="frame">Frame</param> /// <param name="references">.NET module references</param> /// <param name="aliases">Aliases</param> /// <param name="target">Target expression (lhs)</param> /// <param name="expression">Expression (rhs)</param> /// <param name="options">Options</param> /// <param name="cancellationToken">Cancellation token</param> /// <returns></returns> public abstract DbgDotNetCompilationResult CompileAssignment(DbgEvaluationContext context, DbgStackFrame frame, DbgModuleReference[] references, DbgDotNetAlias[] aliases, string target, string expression, DbgEvaluationOptions options, CancellationToken cancellationToken);
public override void Format(DbgEvaluationContext context, DbgStackFrame frame, IDbgValueNodeFormatParameters options, CultureInfo cultureInfo, CancellationToken cancellationToken) { }
public override DbgEngineEvaluationResult Evaluate(DbgEvaluationContext context, DbgStackFrame frame, string expression, DbgEvaluationOptions options, CancellationToken cancellationToken) => new DbgEngineEvaluationResult(ERROR);
/// <summary> /// Constructor /// </summary> /// <param name="context">Evaluation context</param> /// <param name="frame">Stack frame</param> /// <param name="cancellationToken">Cancellation token</param> public DmdEvaluatorContext(DbgEvaluationContext context, DbgStackFrame frame, CancellationToken cancellationToken = default) { EvaluationContext = context; Frame = frame; CancellationToken = cancellationToken; }
/// <summary> /// Evaluates an expression. It blocks the current thread until the evaluation is complete. /// </summary> /// <param name="context">Evaluation context</param> /// <param name="frame">Frame</param> /// <param name="expression">Expression to evaluate</param> /// <param name="options">Options</param> /// <param name="cancellationToken">Cancellation token</param> /// <returns></returns> public abstract DbgEngineEvaluationResult Evaluate(DbgEvaluationContext context, DbgStackFrame frame, string expression, DbgEvaluationOptions options, CancellationToken cancellationToken);
public override DbgEngineValueNode CreateError(DbgEvaluationContext context, DbgStackFrame frame, DbgDotNetText name, string errorMessage, string expression, bool causesSideEffects, CancellationToken cancellationToken) => new DbgEngineValueNodeImpl(this, factory.CreateError(context, frame, name, errorMessage, expression, causesSideEffects, cancellationToken));
public override DbgEngineValueNode CreateTypeVariables(DbgEvaluationContext context, DbgStackFrame frame, DbgDotNetTypeVariableInfo[] typeVariableInfos, CancellationToken cancellationToken) => new DbgEngineValueNodeImpl(this, factory.CreateTypeVariables(context, frame, typeVariableInfos, cancellationToken));
public override DbgEngineValueNode CreateReturnValue(DbgEvaluationContext context, DbgStackFrame frame, uint id, DbgDotNetValue value, DbgValueNodeEvaluationOptions options, DmdMethodBase method, CancellationToken cancellationToken) => new DbgEngineValueNodeImpl(this, factory.CreateReturnValue(context, frame, id, value, options, method, cancellationToken));
public override DbgEngineValueNode CreateStowedException(DbgEvaluationContext context, DbgStackFrame frame, uint id, DbgDotNetValue value, DbgValueNodeEvaluationOptions options, CancellationToken cancellationToken) => new DbgEngineValueNodeImpl(this, factory.CreateStowedException(context, frame, id, value, options, cancellationToken));
public override DbgEngineValueNode Create(DbgEvaluationContext context, DbgStackFrame frame, DbgDotNetText name, DbgDotNetValue value, DbgValueNodeEvaluationOptions options, string expression, string imageName, bool isReadOnly, bool causesSideEffects, DmdType expectedType, CancellationToken cancellationToken) => new DbgEngineValueNodeImpl(this, factory.Create(context, frame, name, value, options, expression, imageName, isReadOnly, causesSideEffects, expectedType, cancellationToken));
public override ulong GetChildCount(DbgEvaluationContext context, DbgStackFrame frame, CancellationToken cancellationToken) => 0;
/// <summary> /// Assigns the value of an expression to another expression. It blocks the current thread until the evaluation is complete. /// </summary> /// <param name="context">Evaluation context</param> /// <param name="frame">Frame</param> /// <param name="expression">Target expression (lhs)</param> /// <param name="valueExpression">Source expression (rhs)</param> /// <param name="options">Options</param> /// <param name="cancellationToken">Cancellation token</param> /// <returns></returns> public abstract DbgEngineEEAssignmentResult Assign(DbgEvaluationContext context, DbgStackFrame frame, string expression, string valueExpression, DbgEvaluationOptions options, CancellationToken cancellationToken);
public override DbgEngineValueNode[] GetChildren(DbgEvaluationContext context, DbgStackFrame frame, ulong index, int count, DbgValueNodeEvaluationOptions options, CancellationToken cancellationToken) => Array.Empty <DbgEngineValueNode>();
DbgEngineLocalsValueNodeInfo[] GetNodesCore(DbgEvaluationContext context, DbgStackFrame frame, DbgValueNodeEvaluationOptions options, DbgLocalsValueNodeEvaluationOptions localsOptions, CancellationToken cancellationToken) { DbgEngineLocalsValueNodeInfo[] valueNodes = null; try { var refsResult = dbgModuleReferenceProvider.GetModuleReferences(context.Runtime, frame); if (refsResult.ErrorMessage != null) { return(Array.Empty <DbgEngineLocalsValueNodeInfo>()); } var languageDebugInfo = context.TryGetLanguageDebugInfo(); if (languageDebugInfo == null) { return(Array.Empty <DbgEngineLocalsValueNodeInfo>()); } var methodDebugInfo = languageDebugInfo.MethodDebugInfo; var module = frame.Module ?? throw new InvalidOperationException(); // Since we attach this to the module, the module doesn't have to be part of Key var state = StateWithKey <GetNodesState> .GetOrCreate(module, this); var localsOptionsKey = localsOptions & ~(DbgLocalsValueNodeEvaluationOptions.ShowCompilerGeneratedVariables | DbgLocalsValueNodeEvaluationOptions.ShowDecompilerGeneratedVariables); var key = new GetNodesState.Key(methodDebugInfo.DecompilerOptionsVersion, options, localsOptionsKey, methodDebugInfo.Method.MDToken.ToInt32(), languageDebugInfo.MethodVersion, refsResult.ModuleReferences, GetScope(methodDebugInfo.Scope, languageDebugInfo.ILOffset)); var evalOptions = DbgEvaluationOptions.None; if ((options & DbgValueNodeEvaluationOptions.NoFuncEval) != 0) { evalOptions |= DbgEvaluationOptions.NoFuncEval; } ValueInfo[] valueInfos; byte[] assemblyBytes; int compilerGeneratedCount; int decompilerGeneratedCount; if (key.Equals(state.CachedKey)) { valueInfos = state.CachedValueInfos; assemblyBytes = state.CachedAssemblyBytes; decompilerGeneratedCount = state.CachedDecompilerGeneratedCount; compilerGeneratedCount = state.CachedCompilerGeneratedCount; } else { var compilationResult = expressionCompiler.CompileGetLocals(context, frame, refsResult.ModuleReferences, evalOptions, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); if (compilationResult.IsError) { return new[] { CreateInternalErrorNode(context, frame, compilationResult.ErrorMessage, cancellationToken) } } ; decompilerGeneratedCount = GetDecompilerGeneratedVariablesCount(methodDebugInfo.Scope, languageDebugInfo.ILOffset); valueInfos = new ValueInfo[compilationResult.CompiledExpressions.Length + decompilerGeneratedCount]; int valueInfosIndex = 0; compilerGeneratedCount = 0; for (int i = 0; i < compilationResult.CompiledExpressions.Length; i++, valueInfosIndex++) { if ((compilationResult.CompiledExpressions[i].ResultFlags & DbgDotNetCompiledExpressionResultFlags.CompilerGenerated) != 0) { compilerGeneratedCount++; } valueInfos[valueInfosIndex] = new CompiledExpressionValueInfo(compilationResult.CompiledExpressions, i); } if (decompilerGeneratedCount > 0) { var scope = methodDebugInfo.Scope; for (;;) { foreach (var local in scope.Locals) { if (local.IsDecompilerGenerated) { valueInfos[valueInfosIndex] = new DecompilerGeneratedVariableValueInfo(local.Name); valueInfosIndex++; } } bool found = false; foreach (var childScope in scope.Scopes) { if (childScope.Span.Start <= languageDebugInfo.ILOffset && languageDebugInfo.ILOffset < childScope.Span.End) { found = true; scope = childScope; break; } } if (!found) { break; } } } if (valueInfos.Length != valueInfosIndex) { throw new InvalidOperationException(); } assemblyBytes = compilationResult.Assembly; state.CachedKey = key; state.CachedValueInfos = valueInfos; state.CachedAssemblyBytes = assemblyBytes; state.CachedILInterpreterState = null; state.CachedDecompilerGeneratedCount = decompilerGeneratedCount; state.CachedCompilerGeneratedCount = compilerGeneratedCount; } int count = valueInfos.Length; if ((localsOptions & DbgLocalsValueNodeEvaluationOptions.ShowCompilerGeneratedVariables) == 0) { count -= compilerGeneratedCount; } if ((localsOptions & DbgLocalsValueNodeEvaluationOptions.ShowDecompilerGeneratedVariables) == 0) { count -= decompilerGeneratedCount; } valueNodes = count == 0 ? Array.Empty <DbgEngineLocalsValueNodeInfo>() : new DbgEngineLocalsValueNodeInfo[count]; var valueCreator = new DbgDotNetValueCreator(valueNodeFactory, dnILInterpreter, context, frame, options, evalOptions, assemblyBytes, cancellationToken); int w = 0; for (int i = 0; i < valueInfos.Length; i++) { cancellationToken.ThrowIfCancellationRequested(); var valueInfo = valueInfos[i]; DbgEngineLocalsValueNodeInfo valueNodeInfo; switch (valueInfo.Kind) { case ValueInfoKind.CompiledExpression: var compExpr = (CompiledExpressionValueInfo)valueInfo; if ((localsOptions & DbgLocalsValueNodeEvaluationOptions.ShowCompilerGeneratedVariables) == 0 && compExpr.IsCompilerGenerated) { continue; } valueNodeInfo = new DbgEngineLocalsValueNodeInfo( compExpr.IsParameter ? DbgLocalsValueNodeKind.Parameter : DbgLocalsValueNodeKind.Local, valueCreator.CreateValueNode(ref state.CachedILInterpreterState, ref compExpr.CompiledExpressionResult)); break; case ValueInfoKind.DecompilerGeneratedVariable: if ((localsOptions & DbgLocalsValueNodeEvaluationOptions.ShowDecompilerGeneratedVariables) == 0) { continue; } var decGen = (DecompilerGeneratedVariableValueInfo)valueInfo; valueNodeInfo = new DbgEngineLocalsValueNodeInfo(DbgLocalsValueNodeKind.Local, valueNodeFactory.CreateError(context, frame, new DbgDotNetText(new DbgDotNetTextPart(BoxedTextColor.Local, decGen.Name)), dnSpy_Debugger_DotNet_Resources.DecompilerGeneratedVariablesCanNotBeEvaluated, decGen.Name, false, cancellationToken)); break; default: throw new InvalidOperationException(); } valueNodes[w++] = valueNodeInfo; } if (w != valueNodes.Length) { throw new InvalidOperationException(); } return(valueNodes); } catch (Exception ex) { if (valueNodes != null) { frame.Process.DbgManager.Close(valueNodes.Select(a => a.ValueNode).Where(a => a != null)); } if (!ExceptionUtils.IsInternalDebuggerError(ex)) { throw; } return(new[] { CreateInternalErrorNode(context, frame, PredefinedEvaluationErrorMessages.InternalDebuggerError, cancellationToken) }); } }
public override DbgEngineValueNodeAssignmentResult Assign(DbgEvaluationContext context, DbgStackFrame frame, string expression, DbgEvaluationOptions options, CancellationToken cancellationToken) => new DbgEngineValueNodeAssignmentResult(DbgEEAssignmentResultFlags.None, NullDbgEngineExpressionEvaluator.ERROR);
DbgEngineLocalsValueNodeInfo CreateInternalErrorNode(DbgEvaluationContext context, DbgStackFrame frame, string errorMessage, CancellationToken cancellationToken) => new DbgEngineLocalsValueNodeInfo(DbgLocalsValueNodeKind.Error, valueNodeFactory.CreateError(context, frame, new DbgDotNetText(new DbgDotNetTextPart(BoxedTextColor.Text, "<error>")), errorMessage, "<internal.error>", false, cancellationToken));
public override DbgEngineEEAssignmentResult Assign(DbgEvaluationContext context, DbgStackFrame frame, string expression, string valueExpression, DbgEvaluationOptions options, CancellationToken cancellationToken) => new DbgEngineEEAssignmentResult(DbgEEAssignmentResultFlags.CompilerError, ERROR);
public override DbgEngineLocalsValueNodeInfo[] GetNodes(DbgEvaluationContext context, DbgStackFrame frame, DbgValueNodeEvaluationOptions options, DbgLocalsValueNodeEvaluationOptions localsOptions, CancellationToken cancellationToken) { var dispatcher = context.Runtime.GetDotNetRuntime().Dispatcher; if (dispatcher.CheckAccess()) { return(GetNodesCore(context, frame, options, localsOptions, cancellationToken)); } return(GetNodes(dispatcher, context, frame, options, localsOptions, cancellationToken)); DbgEngineLocalsValueNodeInfo[] GetNodes(DbgDotNetDispatcher dispatcher2, DbgEvaluationContext context2, DbgStackFrame frame2, DbgValueNodeEvaluationOptions options2, DbgLocalsValueNodeEvaluationOptions localsOptions2, CancellationToken cancellationToken2) => dispatcher2.InvokeRethrow(() => GetNodesCore(context2, frame2, options2, localsOptions2, cancellationToken2)); }
/// <summary> /// Creates an assembly that is used to get all the locals /// </summary> /// <param name="context">Evaluation context</param> /// <param name="frame">Frame</param> /// <param name="references">.NET module references</param> /// <param name="options">Options</param> /// <param name="cancellationToken">Cancellation token</param> /// <returns></returns> public abstract DbgDotNetCompilationResult CompileGetLocals(DbgEvaluationContext context, DbgStackFrame frame, DbgModuleReference[] references, DbgEvaluationOptions options, CancellationToken cancellationToken);
public override DbgEngineValueNode[] GetNodes(DbgEvaluationContext context, DbgStackFrame frame, DbgValueNodeEvaluationOptions options, CancellationToken cancellationToken) => Array.Empty <DbgEngineValueNode>();
/// <summary> /// Called after the <see cref="DbgStackFrame"/> has been created /// </summary> /// <param name="frame">Stack frame</param> public abstract void OnFrameCreated(DbgStackFrame frame);
public override DbgEngineValueNode[] Create(DbgEvaluationContext context, DbgStackFrame frame, DbgExpressionEvaluationInfo[] expressions, CancellationToken cancellationToken) => expressions.Select(a => new NullDbgEngineErrorValueNode(a.Expression)).ToArray();
DbgLocalsValueNodeInfo[] GetSortedVariables(DbgEvaluationContext context, DbgStackFrame frame, DbgLocalsValueNodeInfo[] variables, CultureInfo cultureInfo, CancellationToken cancellationToken) { if (variables.Length <= 1) { return(variables); } var sortParameters = debuggerSettings.SortParameters; var sortLocals = debuggerSettings.SortLocals; // If the default options are used, don't sort at all. Let the locals provider // decide how to sort them. if (!sortParameters && !sortLocals) { return(variables); } var output = new StringBuilderTextColorOutput(); if (debuggerSettings.GroupParametersAndLocalsTogether) { return(variables.OrderBy(a => GetName(context, frame, output, a.ValueNode, cultureInfo, cancellationToken), StringComparer.OrdinalIgnoreCase).ToArray()); } else { var locals = variables.Where(a => a.Kind == DbgLocalsValueNodeKind.Local).ToArray(); var parameters = variables.Where(a => a.Kind == DbgLocalsValueNodeKind.Parameter).ToArray(); var others = variables.Where(a => a.Kind != DbgLocalsValueNodeKind.Local && a.Kind != DbgLocalsValueNodeKind.Parameter).ToArray(); if (sortLocals && locals.Length > 1) { locals = locals.OrderBy(a => GetName(context, frame, output, a.ValueNode, cultureInfo, cancellationToken), StringComparer.OrdinalIgnoreCase).ToArray(); } if (sortParameters && parameters.Length > 1) { parameters = parameters.OrderBy(a => GetName(context, frame, output, a.ValueNode, cultureInfo, cancellationToken), StringComparer.OrdinalIgnoreCase).ToArray(); } if ((sortLocals || sortParameters) && others.Length > 1) { others = others.OrderBy(a => GetName(context, frame, output, a.ValueNode, cultureInfo, cancellationToken), StringComparer.OrdinalIgnoreCase).ToArray(); } var res = new DbgLocalsValueNodeInfo[locals.Length + parameters.Length + others.Length]; int w = 0; for (int i = 0; i < parameters.Length; i++) { res[w++] = parameters[i]; } for (int i = 0; i < locals.Length; i++) { res[w++] = locals[i]; } for (int i = 0; i < others.Length; i++) { res[w++] = others[i]; } if (w != res.Length) { throw new InvalidOperationException(); } return(res); } }
public override DbgEngineValueNode[] Create(DbgEvaluationContext context, DbgStackFrame frame, DbgEngineObjectId[] objectIds, DbgValueNodeEvaluationOptions options, CancellationToken cancellationToken) => objectIds.Select(a => new NullDbgEngineErrorValueNode()).ToArray();
/// <summary> /// Gets the module references or an empty array if <paramref name="frame"/> is an unsupported frame with no .NET module /// </summary> /// <param name="runtime">Runtime</param> /// <param name="frame">Frame</param> /// <returns></returns> public abstract GetModuleReferencesResult GetModuleReferences(DbgRuntime runtime, DbgStackFrame frame);
public abstract DbgEngineValueNode CreateError(DbgEvaluationContext context, DbgStackFrame frame, DbgDotNetText name, string errorMessage, string expression, bool causesSideEffects, CancellationToken cancellationToken);