/// <summary> /// Formats the name, value, and type /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <param name="options">Options</param> /// <param name="cultureInfo">Culture or null to use invariant culture</param> public abstract void Format(DbgEvaluationInfo evalInfo, IDbgValueNodeFormatParameters options, CultureInfo?cultureInfo);
protected override (DbgDotNetValueNode node, bool canHide) CreateValueNode(DbgEvaluationInfo evalInfo, int index, DbgValueNodeEvaluationOptions options, ReadOnlyCollection <string> formatSpecifiers) =>
public override void FormatFrame(DbgEvaluationInfo evalInfo, IDbgTextWriter output, DbgStackFrameFormatterOptions options, DbgValueFormatterOptions valueOptions, CultureInfo?cultureInfo) { }
protected override (DbgDotNetValueNode node, bool canHide) TryCreateInstanceValueNode(DbgEvaluationInfo evalInfo, DbgDotNetValueResult valueResult) { var noResultsNode = DebugViewNoResultsValueNode.TryCreate(evalInfo, Expression, valueResult); if (noResultsNode != null) { valueResult.Value?.Dispose(); return(noResultsNode, false); } return(null, false); }
DbgLocalsValueNodeInfo[] GetSortedVariables(DbgEvaluationInfo evalInfo, DbgLocalsValueNodeInfo[] variables, DbgValueFormatterOptions nameFormatterOptions, CultureInfo?cultureInfo) { 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 DbgStringBuilderTextWriter(); if (debuggerSettings.GroupParametersAndLocalsTogether) { return(variables.OrderBy(a => GetName(evalInfo, output, a.ValueNode, nameFormatterOptions, cultureInfo), 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(evalInfo, output, a.ValueNode, nameFormatterOptions, cultureInfo), StringComparer.OrdinalIgnoreCase).ToArray(); } if (sortParameters && parameters.Length > 1) { parameters = parameters.OrderBy(a => GetName(evalInfo, output, a.ValueNode, nameFormatterOptions, cultureInfo), StringComparer.OrdinalIgnoreCase).ToArray(); } if ((sortLocals || sortParameters) && others.Length > 1) { others = others.OrderBy(a => GetName(evalInfo, output, a.ValueNode, nameFormatterOptions, cultureInfo), 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 void Clear() => evalInfo = null !;
public override DbgDotNetValueNode[] GetChildren(LanguageValueNodeFactory valueNodeFactory, DbgEvaluationInfo evalInfo, ulong index, int count, DbgValueNodeEvaluationOptions options, ReadOnlyCollection <string> formatSpecifiers) { if (count == 0) { return(Array.Empty <DbgDotNetValueNode>()); } var first = providers[0]; ulong childCount = first.GetChildCount(evalInfo); if (index + (uint)count <= childCount) { return(first.GetChildren(valueNodeFactory, evalInfo, index, count, options, formatSpecifiers)); } var res = new DbgDotNetValueNode[count]; try { int w = 0; if (index < childCount) { var tmp = first.GetChildren(valueNodeFactory, evalInfo, index, (int)(childCount - index), options, formatSpecifiers); Array.Copy(tmp, res, tmp.Length); w += tmp.Length; } for (int i = (int)(index - childCount) + 1; i < providers.Length && w < count; i++) { evalInfo.CancellationToken.ThrowIfCancellationRequested(); var provider = providers[i]; res[w++] = valueNodeFactory.Create(evalInfo, provider.Name, provider, formatSpecifiers, options, provider.Expression, provider.ImageName, provider.ValueText); } if (w != res.Length) { throw new InvalidOperationException(); } return(res); } catch { evalInfo.Context.Runtime.Process.DbgManager.Close(res.Where(a => a != null)); throw; } }
public override bool FormatExpectedType(DbgEvaluationInfo evalInfo, IDbgTextWriter output, DbgDotNetFormatter formatter, DbgValueFormatterTypeOptions options, DbgValueFormatterOptions valueOptions, CultureInfo cultureInfo) => columnFormatter?.FormatExpectedType(evalInfo, output, formatter, options, valueOptions, cultureInfo) ?? FormatDebuggerDisplayAttributeType(evalInfo, output, formatter, valueOptions, cultureInfo);
public override ulong GetChildCount(DbgEvaluationInfo evalInfo) => childNodeProvider?.GetChildCount(evalInfo) ?? 0;
/// <summary> /// Creates a new value /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <returns></returns> public abstract DbgEngineValue GetValue(DbgEvaluationInfo evalInfo);
protected override (DbgDotNetValueNode node, bool canHide) CreateValueNode(DbgEvaluationInfo evalInfo, int index, DbgValueNodeEvaluationOptions options, ReadOnlyCollection <string>?formatSpecifiers) { var runtime = evalInfo.Runtime.GetDotNetRuntime(); DbgDotNetValueResult valueResult = default; try { ref var info = ref membersCollection.Members[index]; var typeExpression = GetExpression(info.Member.DeclaringType !); string expression, imageName; bool isReadOnly; DmdType expectedType; switch (info.Member.MemberType) { case DmdMemberTypes.Field: var field = (DmdFieldInfo)info.Member; expression = valueNodeFactory.GetFieldExpression(typeExpression, field.Name, null, addParens: false); expectedType = field.FieldType; imageName = ImageNameUtils.GetImageName(field); valueResult = runtime.LoadField(evalInfo, null, field); // We should be able to change read only fields (we're a debugger), but since the // compiler will complain, we have to prevent the user from editing the value. isReadOnly = field.IsLiteral || field.IsInitOnly; break; case DmdMemberTypes.Property: var property = (DmdPropertyInfo)info.Member; expression = valueNodeFactory.GetPropertyExpression(typeExpression, property.Name, null, addParens: false); expectedType = property.PropertyType; imageName = ImageNameUtils.GetImageName(property); if ((options & DbgValueNodeEvaluationOptions.NoFuncEval) != 0) { isReadOnly = true; valueResult = DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.FuncEvalDisabled); } else { var getter = property.GetGetMethod(DmdGetAccessorOptions.All) ?? throw new InvalidOperationException(); valueResult = runtime.Call(evalInfo, null, getter, Array.Empty <object>(), DbgDotNetInvokeOptions.None); isReadOnly = property.GetSetMethod(DmdGetAccessorOptions.All) is null; } break; default: throw new InvalidOperationException(); } DbgDotNetValueNode newNode; if (valueResult.HasError) { newNode = valueNodeFactory.CreateError(evalInfo, info.Name, valueResult.ErrorMessage !, expression, false); } else if (valueResult.ValueIsException) { newNode = valueNodeFactory.Create(evalInfo, info.Name, valueResult.Value !, formatSpecifiers, options, expression, PredefinedDbgValueNodeImageNames.Error, true, false, expectedType, false); } else { newNode = valueNodeFactory.Create(evalInfo, info.Name, valueResult.Value !, formatSpecifiers, options, expression, imageName, isReadOnly, false, expectedType, false); } valueResult = default; return(newNode, true); }
/// <summary> /// Creates new children /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <param name="index">Index of first child</param> /// <param name="count">Max number of children to return</param> /// <param name="options">Options</param> /// <returns></returns> public abstract DbgEngineValueNode[] GetChildren(DbgEvaluationInfo evalInfo, ulong index, int count, DbgValueNodeEvaluationOptions options);
/// <summary> /// Number of children. This method is called as late as possible and can be lazily initialized. /// It's assumed to be 0 if <see cref="HasChildren"/> is false. /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <returns></returns> public abstract ulong GetChildCount(DbgEvaluationInfo evalInfo);
/// <summary> /// Writes a new value /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <param name="expression">Source expression (rhs)</param> /// <param name="options">Options</param> /// <returns></returns> public abstract DbgEngineValueNodeAssignmentResult Assign(DbgEvaluationInfo evalInfo, string expression, DbgEvaluationOptions options);
/// <summary> /// Formats a value's type /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <param name="output">Output</param> /// <param name="value">Value to format</param> /// <param name="options">Options</param> /// <param name="cultureInfo">Culture or null to use invariant culture</param> public abstract void FormatType(DbgEvaluationInfo evalInfo, IDbgTextWriter output, DbgEngineValue value, DbgValueFormatterTypeOptions options, CultureInfo cultureInfo);
/// <summary> /// Creates a value node /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <param name="name">Name</param> /// <param name="value">Value</param> /// <param name="formatSpecifiers">Format specifiers or null</param> /// <param name="options">Options</param> /// <param name="expression">Expression</param> /// <param name="imageName">Image name, see <see cref="PredefinedDbgValueNodeImageNames"/></param> /// <param name="isReadOnly">true if it's a read-only value</param> /// <param name="causesSideEffects">true if the expression causes side effects</param> /// <param name="expectedType">Expected type</param> /// <returns></returns> public abstract DbgDotNetValueNode Create(DbgEvaluationInfo evalInfo, DbgDotNetText name, DbgDotNetValue value, ReadOnlyCollection <string>?formatSpecifiers, DbgValueNodeEvaluationOptions options, string expression, string imageName, bool isReadOnly, bool causesSideEffects, DmdType expectedType);
public override void Initialize(DbgEvaluationInfo evalInfo, DmdMethodBase method, DmdMethodBody body) => this.evalInfo = evalInfo;
/// <summary> /// Creates an exception value node /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <param name="id">Stowed exception id</param> /// <param name="value">Value</param> /// <param name="formatSpecifiers">Format specifiers or null</param> /// <param name="options">Options</param> /// <returns></returns> public abstract DbgDotNetValueNode CreateStowedException(DbgEvaluationInfo evalInfo, uint id, DbgDotNetValue value, ReadOnlyCollection <string>?formatSpecifiers, DbgValueNodeEvaluationOptions options);
public override ulong GetChildCount(DbgEvaluationInfo evalInfo) => providers[0].GetChildCount(evalInfo) + (uint)(providers.Length - 1);
/// <summary> /// Creates a return value node /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <param name="id">Return value id</param> /// <param name="value">Value</param> /// <param name="formatSpecifiers">Format specifiers or null</param> /// <param name="options">Options</param> /// <param name="method">Method</param> /// <returns></returns> public abstract DbgDotNetValueNode CreateReturnValue(DbgEvaluationInfo evalInfo, uint id, DbgDotNetValue value, ReadOnlyCollection <string>?formatSpecifiers, DbgValueNodeEvaluationOptions options, DmdMethodBase method);
void Create(DbgEvaluationInfo evalInfo, List <DbgDotNetValueNodeProvider> providers, bool addParens, DmdType slotType, DbgDotNetValueNodeInfo nodeInfo, DbgValueNodeEvaluationOptions options, CreationOptions creationOptions) => CreateCore(evalInfo, providers, addParens, slotType, nodeInfo, GetTypeState(nodeInfo), options, creationOptions);
/// <summary> /// Creates an error value node /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <param name="name">Name</param> /// <param name="errorMessage">Error message</param> /// <param name="expression">Expression</param> /// <param name="causesSideEffects">true if the expression causes side effects</param> /// <returns></returns> public abstract DbgDotNetValueNode CreateError(DbgEvaluationInfo evalInfo, DbgDotNetText name, string errorMessage, string expression, bool causesSideEffects);
public override ValueNodesProviderResult GetNodes(DbgEvaluationInfo evalInfo, DbgLanguage language, DbgEvaluationOptions evalOptions, DbgValueNodeEvaluationOptions nodeEvalOptions, DbgValueFormatterOptions nameFormatterOptions) { var recreateAllNodes = forceRecreateAllNodes; forceRecreateAllNodes = false; const CultureInfo?cultureInfo = null; var exceptions = language.ExceptionsProvider.GetNodes(evalInfo, nodeEvalOptions); var returnValues = debuggerSettings.ShowReturnValues ? language.ReturnValuesProvider.GetNodes(evalInfo, nodeEvalOptions) : Array.Empty <DbgValueNode>(); var variables = language.LocalsProvider.GetNodes(evalInfo, nodeEvalOptions, GetLocalsValueNodeOptions()); var typeVariables = language.TypeVariablesProvider.GetNodes(evalInfo, nodeEvalOptions); var objectIds = dbgObjectIdService.GetObjectIds(evalInfo.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(evalInfo, 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(evalInfo, variables, nameFormatterOptions, cultureInfo); 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)); }
/// <summary> /// Creates type variables value node /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <param name="typeVariableInfos">Type variables</param> /// <returns></returns> public abstract DbgDotNetValueNode CreateTypeVariables(DbgEvaluationInfo evalInfo, DbgDotNetTypeVariableInfo[] typeVariableInfos);
string GetName(DbgEvaluationInfo evalInfo, DbgStringBuilderTextWriter output, DbgValueNode valueNode, DbgValueFormatterOptions options, CultureInfo?cultureInfo) { output.Reset(); valueNode.FormatName(evalInfo, output, options, cultureInfo); return(output.ToString()); }
public MonoTypeLoaderImpl(DbgEngineImpl engine, DbgEvaluationInfo evalInfo) { this.engine = engine; this.evalInfo = evalInfo; }
protected override (DbgDotNetValueNode node, bool canHide) TryCreateInstanceValueNode(DbgEvaluationInfo evalInfo, in DbgDotNetValueResult valueResult)
/// <summary> /// Formats a stack frame /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <param name="output">Output</param> /// <param name="options">Stack frame options</param> /// <param name="valueOptions">Value option</param> /// <param name="cultureInfo">Culture or null to use invariant culture</param> public abstract void FormatFrame(DbgEvaluationInfo evalInfo, IDbgTextWriter output, DbgStackFrameFormatterOptions options, DbgValueFormatterOptions valueOptions, CultureInfo cultureInfo);
public override void FormatValue(DbgEvaluationInfo evalInfo, IDbgTextWriter output, DbgEngineValue value, DbgValueFormatterOptions options, CultureInfo?cultureInfo) { }
internal string StoreValue_CorDebug(DbgEvaluationInfo evalInfo, ILDbgEngineStackFrame ilFrame, Func <CreateCorValueResult> createTargetValue, DmdType targetType, object sourceValue) { debuggerThread.VerifyAccess(); if (RequiresNoFuncEvalToStoreValue(targetType, sourceValue)) { return(StoreSimpleValue_CorDebug(evalInfo, ilFrame, createTargetValue, targetType, sourceValue)); } evalInfo.CancellationToken.ThrowIfCancellationRequested(); var tmp = CheckFuncEval(evalInfo); if (tmp != null) { return(tmp.Value.ErrorMessage ?? throw new InvalidOperationException()); } var dnThread = GetThread(evalInfo.Frame.Thread); var createdValues = new List <CorValue>(); CreateCorValueResult createResult = default; try { var appDomain = ilFrame.GetCorAppDomain(); var reflectionAppDomain = targetType.AppDomain; using (var dnEval = dnDebugger.CreateEval(evalInfo.CancellationToken, suspendOtherThreads: (evalInfo.Context.Options & DbgEvaluationContextOptions.RunAllThreads) == 0)) { dnEval.SetThread(dnThread); dnEval.SetTimeout(evalInfo.Context.FuncEvalTimeout); dnEval.EvalEvent += (s, e) => DnEval_EvalEvent(dnEval, evalInfo); var converter = new EvalArgumentConverter(this, dnEval, appDomain, reflectionAppDomain, createdValues); var evalRes = converter.Convert(sourceValue, targetType, out var newValueType); if (evalRes.ErrorMessage != null) { return(evalRes.ErrorMessage); } var sourceCorValue = evalRes.CorValue; var sourceType = new ReflectionTypeCreator(this, reflectionAppDomain).Create(sourceCorValue.ExactType); createResult = createTargetValue(); if (createResult.Value == null) { return(CordbgErrorHelper.GetErrorMessage(createResult.HResult)); } return(StoreValue_CorDebug(dnEval, createdValues, appDomain, dnThread, createResult.Value, targetType, sourceCorValue, sourceType)); } } catch (TimeoutException) { return(PredefinedEvaluationErrorMessages.FuncEvalTimedOut); } catch (Exception ex) when(ExceptionUtils.IsInternalDebuggerError(ex)) { return(CordbgErrorHelper.InternalError); } finally { if (createResult.CanDispose) { dnDebugger.DisposeHandle(createResult.Value); } foreach (var v in createdValues) { dnDebugger.DisposeHandle(v); } } }