internal static DkmEvaluationResult EvalResult( string name, string value, string type, string fullName, DkmEvaluationResultFlags flags = DkmEvaluationResultFlags.None, DkmEvaluationResultCategory category = UnspecifiedCategory, DkmEvaluationResultAccessType access = UnspecifiedAccessType, string editableValue = null, DkmCustomUIVisualizerInfo[] customUIVisualizerInfo = null) { return(DkmSuccessEvaluationResult.Create( null, null, name, fullName, flags, value, editableValue, type, category, access, default(DkmEvaluationResultStorageType), default(DkmEvaluationResultTypeModifierFlags), null, (customUIVisualizerInfo != null) ? new ReadOnlyCollection <DkmCustomUIVisualizerInfo>(customUIVisualizerInfo) : null, null, null)); }
internal static DkmEvaluationResult EvaluateDataAtLuaValue(DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, string name, string fullName, LuaValueDataBase luaValue, DkmEvaluationResultFlags flags, DkmEvaluationResultAccessType access, DkmEvaluationResultStorageType storage) { var process = stackFrame.Process; if (luaValue == null) { return(DkmFailedEvaluationResult.Create(inspectionContext, stackFrame, name, fullName, "Null pointer access", DkmEvaluationResultFlags.Invalid, null)); } string value = EvaluateValueAtLuaValue(process, luaValue, inspectionContext.Radix, out string editableValue, ref flags, out DkmDataAddress dataAddress, out string type); if (value == null) { return(DkmFailedEvaluationResult.Create(inspectionContext, stackFrame, name, fullName, "Failed to read value", DkmEvaluationResultFlags.Invalid, null)); } DkmEvaluationResultCategory category = DkmEvaluationResultCategory.Data; DkmEvaluationResultTypeModifierFlags typeModifiers = DkmEvaluationResultTypeModifierFlags.None; var dataItem = new LuaEvaluationDataItem { address = luaValue.originalAddress, type = type, fullName = fullName, luaValueData = luaValue }; return(DkmSuccessEvaluationResult.Create(inspectionContext, stackFrame, name, fullName, flags, value, editableValue, type, category, access, storage, typeModifiers, dataAddress, null, null, dataItem)); }
private static DkmEvaluationResult CreateEvaluationResult( DkmInspectionContext inspectionContext, DkmClrValue value, string name, string typeName, string display, EvalResultDataItem dataItem) { if (value.IsError()) { // Evaluation failed return(DkmFailedEvaluationResult.Create( InspectionContext: inspectionContext, StackFrame: value.StackFrame, Name: name, FullName: dataItem.FullName, ErrorMessage: display, Flags: dataItem.Flags, Type: typeName, DataItem: dataItem)); } else { ReadOnlyCollection <DkmCustomUIVisualizerInfo> customUIVisualizers = null; if (!value.IsNull) { DkmCustomUIVisualizerInfo[] customUIVisualizerInfo = value.Type.GetDebuggerCustomUIVisualizerInfo(); if (customUIVisualizerInfo != null) { customUIVisualizers = new ReadOnlyCollection <DkmCustomUIVisualizerInfo>(customUIVisualizerInfo); } } // If the EvalResultData item doesn't specify a particular category, we'll just propagate DkmClrValue.Category, // which typically appears to be set to the default value ("Other"). var category = (dataItem.Category != DkmEvaluationResultCategory.Other) ? dataItem.Category : value.Category; // Valid value return(DkmSuccessEvaluationResult.Create( InspectionContext: inspectionContext, StackFrame: value.StackFrame, Name: name, FullName: dataItem.FullName, Flags: dataItem.Flags, Value: display, EditableValue: dataItem.EditableValue, Type: typeName, Category: category, Access: value.Access, StorageType: value.StorageType, TypeModifierFlags: value.TypeModifierFlags, Address: value.Address, CustomUIVisualizers: customUIVisualizers, ExternalModules: null, DataItem: dataItem)); } }
void IDkmCustomVisualizer.EvaluateVisualizedExpression(DkmVisualizedExpression expression, out DkmEvaluationResult resultObject) { BasicVisualizer visualizer = null; DkmFailedEvaluationResult failureResult = null; if (!TryGetRegisteredVisualizer(expression, out visualizer, out failureResult)) { resultObject = failureResult; return; } DkmEvaluationResult evalResult = visualizer.EvaluationResult; EvaluationDataItem resultDataItem = new EvaluationDataItem(expression, evalResult); expression.SetDataItem(DkmDataCreationDisposition.CreateAlways, resultDataItem); string name = null; string fullName = null; Utility.GetExpressionName(expression, out name, out fullName); if (evalResult.TagValue == DkmEvaluationResult.Tag.SuccessResult) { DkmSuccessEvaluationResult successResult = (DkmSuccessEvaluationResult)evalResult; resultObject = DkmSuccessEvaluationResult.Create( successResult.InspectionContext, successResult.StackFrame, name, successResult.FullName, successResult.Flags, successResult.Value, successResult.EditableValue, successResult.Type, successResult.Category, successResult.Access, successResult.StorageType, successResult.TypeModifierFlags, successResult.Address, successResult.CustomUIVisualizers, successResult.ExternalModules, resultDataItem); } else { DkmFailedEvaluationResult failResult = (DkmFailedEvaluationResult)evalResult; resultObject = DkmFailedEvaluationResult.Create( failResult.InspectionContext, failResult.StackFrame, name, fullName, failResult.ErrorMessage, failResult.Flags, null); return; } }
internal static DkmEvaluationResult GetLuaFunctionChildAtIndex(DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, string fullName, LuaClosureData value, int index) { var process = stackFrame.Process; var processData = DebugHelpers.GetOrCreateDataItem <LuaLocalProcessData>(process); if (index == 0) { if (value == null) { return(DkmFailedEvaluationResult.Create(inspectionContext, stackFrame, "[function]", $"{fullName}.!function", "null", DkmEvaluationResultFlags.Invalid, null)); } var functionData = value.ReadFunction(process); if (functionData == null) { return(DkmFailedEvaluationResult.Create(inspectionContext, stackFrame, "[function]", $"{fullName}.!function", "[internal error: failed to read Proto]", DkmEvaluationResultFlags.Invalid, null)); } string source = functionData.ReadSource(process); if (source == null) { return(DkmFailedEvaluationResult.Create(inspectionContext, stackFrame, "[function]", $"{fullName}.!function", "[internal error: failed to read source]", DkmEvaluationResultFlags.Invalid, null)); } int line = functionData.definitionStartLine_opt; DkmEvaluationResultCategory category = DkmEvaluationResultCategory.Method; DkmEvaluationResultTypeModifierFlags typeModifiers = DkmEvaluationResultTypeModifierFlags.None; DkmEvaluationResultAccessType access = DkmEvaluationResultAccessType.Public; DkmEvaluationResultStorageType storage = DkmEvaluationResultStorageType.Global; LuaAddressEntityData entityData = new LuaAddressEntityData { source = source, line = line, functionAddress = 0, functionInstructionPointer = 0, }; var entityDataBytes = entityData.Encode(); DkmInstructionAddress instructionAddress = DkmCustomInstructionAddress.Create(processData.runtimeInstance, processData.moduleInstance, entityDataBytes, (ulong)((line << 16) + 0), null, null); DkmDataAddress dataAddress = DkmDataAddress.Create(processData.runtimeInstance, value.functionAddress, instructionAddress); return(DkmSuccessEvaluationResult.Create(inspectionContext, stackFrame, "[function]", $"{fullName}.!function", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Address, $"{source}:{line}", null, "Proto*", category, access, storage, typeModifiers, dataAddress, null, null, null)); } Debug.Assert(false, "Invalid child index"); return(null); }
void IDkmClrResultProvider.GetResult(DkmClrValue clrValue, DkmWorkList workList, DkmClrType declaredType, DkmClrCustomTypeInfo customTypeInfo, DkmInspectionContext inspectionContext, ReadOnlyCollection <string> formatSpecifiers, string resultName, string resultFullName, DkmCompletionRoutine <DkmEvaluationAsyncResult> completionRoutine) { clrValue.GetResult( workList, declaredType, customTypeInfo, inspectionContext, formatSpecifiers, resultName, resultFullName, result => { var type = declaredType.GetLmrType(); if (type.IsPointer) { var r = (DkmSuccessEvaluationResult)result.Result; // TODO: Why aren't modopts for & properties included? r.GetChildren( workList, 1, inspectionContext, children => { var c = (DkmSuccessEvaluationResult)children.InitialChildren[0]; r = DkmSuccessEvaluationResult.Create( c.InspectionContext, c.StackFrame, r.Name, r.FullName, c.Flags, c.Value, r.EditableValue, r.Type, r.Category, r.Access, r.StorageType, r.TypeModifierFlags, null, r.CustomUIVisualizers, null, null); completionRoutine(new DkmEvaluationAsyncResult(r)); }); } else { completionRoutine(result); } }); }
private DkmChildVisualizedExpression[] Convert(DkmVisualizedExpression visualizedExpression, DkmEvaluationResult[] itemsAsResult, int startIndex = 0) { DkmChildVisualizedExpression[] items = new DkmChildVisualizedExpression[itemsAsResult.Length]; for (int i = 0; i < items.Length; i++) { DkmEvaluationResult result = itemsAsResult[i]; PassThroughVisualizer defaultEvaluator = null; if (result is DkmSuccessEvaluationResult successResult) { defaultEvaluator = new PassThroughVisualizer(successResult); result = DkmSuccessEvaluationResult.Create( successResult.InspectionContext, successResult.StackFrame, successResult.Name, // Name - Left column successResult.FullName, successResult.Flags, successResult.Value, // Value - Middle column successResult.EditableValue, successResult.Type, // Type - Right column successResult.Category, successResult.Access, successResult.StorageType, successResult.TypeModifierFlags, successResult.Address, successResult.CustomUIVisualizers, successResult.ExternalModules, successResult.RefreshButtonText, defaultEvaluator); } items[i] = DkmChildVisualizedExpression.Create( visualizedExpression.InspectionContext, visualizedExpression.VisualizerId, visualizedExpression.SourceId, visualizedExpression.StackFrame, null, result, visualizedExpression, (uint)(startIndex + i), defaultEvaluator); } return(items); }
private DkmEvaluationResult GetRow(ResultProvider resultProvider, DkmClrValue value, int index, EvalResultDataItem parent) { var inspectionContext = value.InspectionContext; var appDomain = value.Type.AppDomain; var typeParameter = _typeParameters[index]; var typeArgument = _typeArguments[index]; var type = DkmClrType.Create(appDomain, typeArgument); var name = typeParameter.Name; var dataItem = new EvalResultDataItem( name, typeDeclaringMember: null, declaredType: typeArgument, value: null, expansion: null, childShouldParenthesize: false, fullName: null, childFullNamePrefixOpt: null, formatSpecifiers: Formatter.NoFormatSpecifiers, category: DkmEvaluationResultCategory.Data, flags: DkmEvaluationResultFlags.ReadOnly, editableValue: null); var typeName = inspectionContext.GetTypeName(DkmClrType.Create(appDomain, typeArgument)); return(DkmSuccessEvaluationResult.Create( inspectionContext, value.StackFrame, name, dataItem.FullName, dataItem.Flags, Value: typeName, EditableValue: null, Type: typeName, Category: dataItem.Category, Access: value.Access, StorageType: value.StorageType, TypeModifierFlags: value.TypeModifierFlags, Address: value.Address, CustomUIVisualizers: null, ExternalModules: null, DataItem: dataItem)); }
internal static DkmEvaluationResult EvaluateCppExpression(DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, string name, string expression) { DkmEvaluationResult result = ExecuteRawExpression(expression, inspectionContext.InspectionSession, inspectionContext.Thread, stackFrame, inspectionContext.Thread.Process.GetNativeRuntimeInstance(), DkmEvaluationFlags.TreatAsExpression); if (result is DkmSuccessEvaluationResult success) { var renamedResult = DkmSuccessEvaluationResult.Create(success.InspectionContext, success.StackFrame, name, success.FullName, success.Flags, success.Value, success.EditableValue, success.Type, success.Category, success.Access, success.StorageType, success.TypeModifierFlags, success.Address, success.CustomUIVisualizers, success.ExternalModules, success.RefreshButtonText, null); result.Close(); return(renamedResult); } else if (result is DkmFailedEvaluationResult faliure) { var renamedResult = DkmFailedEvaluationResult.Create(faliure.InspectionContext, faliure.StackFrame, name, faliure.FullName, faliure.ErrorMessage, faliure.Flags, faliure.Type, faliure.Category, null); result.Close(); return(renamedResult); } return(DkmFailedEvaluationResult.Create(inspectionContext, stackFrame, name, expression, "Aborted", DkmEvaluationResultFlags.Invalid, "(void*)", null)); }
private static DkmEvaluationResult CreateEvaluationResult( DkmInspectionContext inspectionContext, DkmClrValue value, string name, string typeName, string display, EvalResultDataItem dataItem) { if (value.IsError()) { // Evaluation failed return(DkmFailedEvaluationResult.Create( InspectionContext: inspectionContext, StackFrame: value.StackFrame, Name: name, FullName: dataItem.FullName, ErrorMessage: display, Flags: dataItem.Flags, Type: typeName, DataItem: dataItem)); } else if (dataItem.Kind == ExpansionKind.NativeView) { // For Native View, create a DkmIntermediateEvaluationResult. This will allow the C++ EE // to take over expansion. DkmProcess process = inspectionContext.RuntimeInstance.Process; DkmLanguage cpp = process.EngineSettings.GetLanguage(new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.Cpp)); return(DkmIntermediateEvaluationResult.Create( InspectionContext: inspectionContext, StackFrame: value.StackFrame, Name: Resources.NativeView, FullName: dataItem.FullName, Expression: dataItem.Name, IntermediateLanguage: cpp, TargetRuntime: process.GetNativeRuntimeInstance(), DataItem: dataItem)); } else { ReadOnlyCollection <DkmCustomUIVisualizerInfo> customUIVisualizers = null; if (!value.IsNull) { DkmCustomUIVisualizerInfo[] customUIVisualizerInfo = value.Type.GetDebuggerCustomUIVisualizerInfo(); if (customUIVisualizerInfo != null) { customUIVisualizers = new ReadOnlyCollection <DkmCustomUIVisualizerInfo>(customUIVisualizerInfo); } } // If the EvalResultData item doesn't specify a particular category, we'll just propagate DkmClrValue.Category, // which typically appears to be set to the default value ("Other"). var category = (dataItem.Category != DkmEvaluationResultCategory.Other) ? dataItem.Category : value.Category; // Valid value return(DkmSuccessEvaluationResult.Create( InspectionContext: inspectionContext, StackFrame: value.StackFrame, Name: name, FullName: dataItem.FullName, Flags: dataItem.Flags, Value: display, EditableValue: dataItem.EditableValue, Type: typeName, Category: category, Access: value.Access, StorageType: value.StorageType, TypeModifierFlags: value.TypeModifierFlags, Address: value.Address, CustomUIVisualizers: customUIVisualizers, ExternalModules: null, DataItem: dataItem)); } }
private void CreateEvaluationResultAndContinue(EvalResultDataItem dataItem, DkmWorkList workList, DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, CompletionRoutine <DkmEvaluationResult> completionRoutine) { switch (dataItem.Kind) { case ExpansionKind.Error: completionRoutine(DkmFailedEvaluationResult.Create( inspectionContext, StackFrame: stackFrame, Name: dataItem.Name, FullName: dataItem.FullName, ErrorMessage: dataItem.DisplayValue, Flags: DkmEvaluationResultFlags.None, Type: null, DataItem: null)); break; case ExpansionKind.NonPublicMembers: case ExpansionKind.StaticMembers: completionRoutine(CreateEvaluationResult( inspectionContext, dataItem.Value, dataItem.Name, typeName: string.Empty, display: null, dataItem: dataItem)); break; case ExpansionKind.RawView: completionRoutine(CreateEvaluationResult( inspectionContext, dataItem.Value, Resources.RawView, typeName: string.Empty, display: null, dataItem: dataItem)); break; case ExpansionKind.ResultsView: completionRoutine(CreateEvaluationResult( inspectionContext, dataItem.Value, dataItem.Name, typeName: string.Empty, display: Resources.ResultsViewValueWarning, dataItem: dataItem)); break; case ExpansionKind.TypeVariables: var value = dataItem.Value; completionRoutine(DkmSuccessEvaluationResult.Create( inspectionContext, stackFrame, dataItem.Name, dataItem.FullName, dataItem.Flags, dataItem.DisplayValue, EditableValue: null, Type: dataItem.DisplayValue, Category: dataItem.Category, Access: value.Access, StorageType: value.StorageType, TypeModifierFlags: value.TypeModifierFlags, Address: value.Address, CustomUIVisualizers: null, ExternalModules: null, DataItem: dataItem)); break; default: Debug.Assert((dataItem.Kind == ExpansionKind.Default) || (dataItem.Kind == ExpansionKind.PointerDereference)); // This call will evaluate DebuggerDisplayAttributes. GetResultAndContinue( dataItem, workList, declaredType: DkmClrType.Create(dataItem.Value.Type.AppDomain, dataItem.DeclaredType), inspectionContext: inspectionContext, parent: dataItem.Parent, completionRoutine: completionRoutine); break; } }
private void GetRootResultAndContinue( DkmClrValue value, WorkList workList, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmInspectionContext inspectionContext, string name, string fullName, ReadOnlyCollection <string> formatSpecifiers, CompletionRoutine <DkmEvaluationResult> completionRoutine) { Debug.Assert(formatSpecifiers != null); var type = value.Type.GetLmrType(); if (type.IsTypeVariables()) { Debug.Assert(type.Equals(declaredType.GetLmrType())); var declaredTypeAndInfo = new TypeAndCustomInfo(declaredType, declaredTypeInfo); var expansion = new TypeVariablesExpansion(declaredTypeAndInfo); var dataItem = new EvalResult( ExpansionKind.Default, name, typeDeclaringMemberAndInfo: default(TypeAndCustomInfo), declaredTypeAndInfo: declaredTypeAndInfo, useDebuggerDisplay: false, value: value, displayValue: null, expansion: expansion, childShouldParenthesize: false, fullName: null, childFullNamePrefixOpt: null, formatSpecifiers: Formatter.NoFormatSpecifiers, category: DkmEvaluationResultCategory.Data, flags: DkmEvaluationResultFlags.ReadOnly, editableValue: null, inspectionContext: inspectionContext); Debug.Assert(dataItem.Flags == (DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable)); // Note: We're not including value.EvalFlags in Flags parameter // below (there shouldn't be a reason to do so). completionRoutine(DkmSuccessEvaluationResult.Create( InspectionContext: inspectionContext, StackFrame: value.StackFrame, Name: Resources.TypeVariablesName, FullName: dataItem.FullName, Flags: dataItem.Flags, Value: "", EditableValue: null, Type: "", Category: dataItem.Category, Access: value.Access, StorageType: value.StorageType, TypeModifierFlags: value.TypeModifierFlags, Address: value.Address, CustomUIVisualizers: null, ExternalModules: null, DataItem: dataItem.ToDataItem())); } else if ((inspectionContext.EvaluationFlags & DkmEvaluationFlags.ResultsOnly) != 0) { var dataItem = ResultsViewExpansion.CreateResultsOnlyRow( inspectionContext, name, fullName, formatSpecifiers, declaredType, declaredTypeInfo, value, this); CreateEvaluationResultAndContinue( dataItem, workList, inspectionContext, value.StackFrame, completionRoutine); } else if ((inspectionContext.EvaluationFlags & DkmEvaluationFlags.DynamicView) != 0) { var dataItem = DynamicViewExpansion.CreateMembersOnlyRow( inspectionContext, name, value, this); CreateEvaluationResultAndContinue( dataItem, workList, inspectionContext, value.StackFrame, completionRoutine); } else { var dataItem = ResultsViewExpansion.CreateResultsOnlyRowIfSynthesizedEnumerable( inspectionContext, name, fullName, formatSpecifiers, declaredType, declaredTypeInfo, value, this); if (dataItem != null) { CreateEvaluationResultAndContinue( dataItem, workList, inspectionContext, value.StackFrame, completionRoutine); } else { var useDebuggerDisplay = (inspectionContext.EvaluationFlags & NotRoot) != 0; var expansionFlags = (inspectionContext.EvaluationFlags & NoResults) != 0 ? ExpansionFlags.IncludeBaseMembers : ExpansionFlags.All; dataItem = CreateDataItem( inspectionContext, name, typeDeclaringMemberAndInfo: default(TypeAndCustomInfo), declaredTypeAndInfo: new TypeAndCustomInfo(declaredType, declaredTypeInfo), value: value, useDebuggerDisplay: useDebuggerDisplay, expansionFlags: expansionFlags, childShouldParenthesize: (fullName == null) ? false : FullNameProvider.ClrExpressionMayRequireParentheses(inspectionContext, fullName), fullName: fullName, formatSpecifiers: formatSpecifiers, category: DkmEvaluationResultCategory.Other, flags: value.EvalFlags, evalFlags: inspectionContext.EvaluationFlags); GetResultAndContinue(dataItem, workList, declaredType, declaredTypeInfo, inspectionContext, useDebuggerDisplay, completionRoutine); } } }
private void CreateEvaluationResultAndContinue(EvalResult result, WorkList workList, DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, CompletionRoutine <DkmEvaluationResult> completionRoutine) { switch (result.Kind) { case ExpansionKind.Error: completionRoutine(DkmFailedEvaluationResult.Create( inspectionContext, StackFrame: stackFrame, Name: result.Name, FullName: result.FullName, ErrorMessage: result.DisplayValue, Flags: DkmEvaluationResultFlags.None, Type: null, DataItem: null)); break; case ExpansionKind.NativeView: { var value = result.Value; var name = Resources.NativeView; var fullName = result.FullName; var display = result.Name; DkmEvaluationResult evalResult; if (value.IsError()) { evalResult = DkmFailedEvaluationResult.Create( inspectionContext, stackFrame, Name: name, FullName: fullName, ErrorMessage: display, Flags: result.Flags, Type: null, DataItem: result.ToDataItem()); } else { // For Native View, create a DkmIntermediateEvaluationResult. // This will allow the C++ EE to take over expansion. var process = inspectionContext.RuntimeInstance.Process; var cpp = process.EngineSettings.GetLanguage(new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.Cpp)); evalResult = DkmIntermediateEvaluationResult.Create( inspectionContext, stackFrame, Name: name, FullName: fullName, Expression: display, IntermediateLanguage: cpp, TargetRuntime: process.GetNativeRuntimeInstance(), DataItem: result.ToDataItem()); } completionRoutine(evalResult); } break; case ExpansionKind.NonPublicMembers: completionRoutine(DkmSuccessEvaluationResult.Create( inspectionContext, stackFrame, Name: Resources.NonPublicMembers, FullName: result.FullName, Flags: result.Flags, Value: null, EditableValue: null, Type: string.Empty, Category: DkmEvaluationResultCategory.Data, Access: DkmEvaluationResultAccessType.None, StorageType: DkmEvaluationResultStorageType.None, TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None, Address: result.Value.Address, CustomUIVisualizers: null, ExternalModules: null, DataItem: result.ToDataItem())); break; case ExpansionKind.StaticMembers: completionRoutine(DkmSuccessEvaluationResult.Create( inspectionContext, stackFrame, Name: StaticMembersString, FullName: result.FullName, Flags: result.Flags, Value: null, EditableValue: null, Type: string.Empty, Category: DkmEvaluationResultCategory.Class, Access: DkmEvaluationResultAccessType.None, StorageType: DkmEvaluationResultStorageType.None, TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None, Address: result.Value.Address, CustomUIVisualizers: null, ExternalModules: null, DataItem: result.ToDataItem())); break; case ExpansionKind.RawView: completionRoutine(DkmSuccessEvaluationResult.Create( inspectionContext, stackFrame, Name: Resources.RawView, FullName: result.FullName, Flags: result.Flags, Value: null, EditableValue: result.EditableValue, Type: string.Empty, Category: DkmEvaluationResultCategory.Data, Access: DkmEvaluationResultAccessType.None, StorageType: DkmEvaluationResultStorageType.None, TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None, Address: result.Value.Address, CustomUIVisualizers: null, ExternalModules: null, DataItem: result.ToDataItem())); break; case ExpansionKind.DynamicView: case ExpansionKind.ResultsView: completionRoutine(DkmSuccessEvaluationResult.Create( inspectionContext, stackFrame, result.Name, result.FullName, result.Flags, result.DisplayValue, EditableValue: null, Type: string.Empty, Category: DkmEvaluationResultCategory.Method, Access: DkmEvaluationResultAccessType.None, StorageType: DkmEvaluationResultStorageType.None, TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None, Address: result.Value.Address, CustomUIVisualizers: null, ExternalModules: null, DataItem: result.ToDataItem())); break; case ExpansionKind.TypeVariable: completionRoutine(DkmSuccessEvaluationResult.Create( inspectionContext, stackFrame, result.Name, result.FullName, result.Flags, result.DisplayValue, EditableValue: null, Type: result.DisplayValue, Category: DkmEvaluationResultCategory.Data, Access: DkmEvaluationResultAccessType.None, StorageType: DkmEvaluationResultStorageType.None, TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None, Address: result.Value.Address, CustomUIVisualizers: null, ExternalModules: null, DataItem: result.ToDataItem())); break; case ExpansionKind.PointerDereference: case ExpansionKind.Default: // This call will evaluate DebuggerDisplayAttributes. GetResultAndContinue( result, workList, declaredType: result.DeclaredTypeAndInfo.ClrType, declaredTypeInfo: result.DeclaredTypeAndInfo.Info, inspectionContext: inspectionContext, useDebuggerDisplay: result.UseDebuggerDisplay, completionRoutine: completionRoutine); break; default: throw ExceptionUtilities.UnexpectedValue(result.Kind); } }
protected DkmEvaluationResult GeneratePropertyValueEval(string container_expr_str, string uprop_expr_str, uint index, DkmVisualizedExpression context_expr) { Debug.Print("UE4PV: Trying to generate property value for property #{0}", index + 1); var uprop_em = ExpressionManipulator.FromExpression(uprop_expr_str); // Get name of property string prop_name_expr_str = uprop_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression; string prop_name = UE4Utility.GetFNameAsString(prop_name_expr_str, context_expr); // And the property type string prop_type = GetPropertyType(uprop_em.Expression, context_expr); // Now, determine address of the actual property value // First requires container address // Cast to void* first, so that expression evaluation is simplified and faster container_expr_str = ExpressionManipulator.FromExpression(container_expr_str).PtrCast(Cpp.Void).Expression; var container_eval = DefaultEE.DefaultEval(container_expr_str, context_expr, true) as DkmSuccessEvaluationResult; Debug.Assert(container_eval != null && container_eval.Address != null); string address_str = container_eval.Address.Value.ToString(); // Next need offset in container (which is an int32 property of the UProperty class) var offset_expr_str = uprop_em.PtrMember(Memb.PropOffset).Expression; var offset_eval = DefaultEE.DefaultEval(offset_expr_str, context_expr, true) as DkmSuccessEvaluationResult; string offset_str = offset_eval.Value; // Then need to create an expression which adds on the offset address_str = String.Format("((uint8*){0} + {1})", address_str, offset_str); // Next, we need to cast this expression depending on the type of property we have. // Retrieve a list of possible cast expressions. var cpp_type_info_list = GetCppTypeForPropertyType(prop_type, uprop_em.Expression, context_expr); // Accept the first one that is successfully evaluated DkmSuccessEvaluationResult success_eval = null; string display_type = null; foreach (var cpp_type_info in cpp_type_info_list) { string prop_value_expr_str = AdjustPropertyExpressionStringForType(address_str, prop_type, uprop_em.Expression, context_expr, cpp_type_info); Debug.Print("UE4PV: Attempting exp eval as: '{0}'", prop_value_expr_str); // Attempt to evaluate the expression DkmEvaluationResult raw_eval = DefaultEE.DefaultEval(prop_value_expr_str, context_expr, false); if (raw_eval.TagValue == DkmEvaluationResult.Tag.SuccessResult) { // Success success_eval = raw_eval as DkmSuccessEvaluationResult; display_type = cpp_type_info.Display; break; } } if (success_eval == null) { // Was not able to find an evaluatable expression. return(null); } return(DkmSuccessEvaluationResult.Create( expression_.InspectionContext, expression_.StackFrame, prop_name, success_eval.FullName, //prop_value_expr_str, success_eval.Flags, success_eval.Value, // @TODO: Perhaps need to disable for some stuff, like bitfield bool? success_eval.EditableValue, display_type, //success_eval.Type, success_eval.Category, success_eval.Access, success_eval.StorageType, success_eval.TypeModifierFlags, success_eval.Address, success_eval.CustomUIVisualizers, success_eval.ExternalModules, null )); }
/// <summary> /// Returns child elements of previous evaluation. /// </summary> public void GetItems(DkmVisualizedExpression visualizedExpression, DkmEvaluationResultEnumContext enumContext, int startIndex, int count, out DkmChildVisualizedExpression[] items) { // Check if we want to use passthrough visualizer PassThroughVisualizer passThroughVisualizer = enumContext.GetDataItem <PassThroughVisualizer>(); if (passThroughVisualizer != null) { passThroughVisualizer.GetItems(visualizedExpression, enumContext, startIndex, count, out items); return; } // Execute our regular visualizer VSCustomVisualizerEvaluator evaluator = visualizedExpression.GetDataItem <VSCustomVisualizerEvaluator>(); IResultVisualizer[] itemsAsResults = evaluator.ResultVisualizer.Children.Skip(startIndex).Take(count).ToArray(); items = new DkmChildVisualizedExpression[itemsAsResults.Length]; for (int i = 0; i < items.Length; i++) { IResultVisualizer item = itemsAsResults[i]; DkmEvaluationResultCategory category; switch (item.DataType) { case CompletionDataType.Class: category = DkmEvaluationResultCategory.Class; break; case CompletionDataType.Property: case CompletionDataType.StaticProperty: category = DkmEvaluationResultCategory.Property; break; case CompletionDataType.Event: category = DkmEvaluationResultCategory.Event; break; case CompletionDataType.Method: category = DkmEvaluationResultCategory.Method; break; case CompletionDataType.Enum: case CompletionDataType.EnumValue: case CompletionDataType.Keyword: case CompletionDataType.Namespace: case CompletionDataType.StaticClass: case CompletionDataType.StaticEvent: case CompletionDataType.StaticMethod: case CompletionDataType.StaticVariable: case CompletionDataType.Unknown: case CompletionDataType.Variable: default: category = DkmEvaluationResultCategory.Data; break; } DkmExpressionValueHome valueHome = visualizedExpression.ValueHome; ulong address = 0; string fullName = string.Empty; string typeName = null; try { if (item.Value is Variable variable) { address = variable.GetPointerAddress(); typeName = variable.GetCodeType().Name; fullName = $"*(({typeName}*)0x{address:X})"; valueHome = DkmPointerValueHome.Create(address); } } catch { } DkmEvaluationResult result; DkmDataItem dataItem = null; if (item.ShouldForceDefaultVisualizer && !string.IsNullOrEmpty(fullName)) { using (DkmLanguageExpression languageExpression = DkmLanguageExpression.Create(visualizedExpression.InspectionContext.Language, DkmEvaluationFlags.TreatAsExpression, fullName, null)) { visualizedExpression.EvaluateExpressionCallback(visualizedExpression.InspectionContext, languageExpression, visualizedExpression.StackFrame, out result); } if (result is DkmSuccessEvaluationResult successResult) { dataItem = new PassThroughVisualizer(successResult); result = DkmSuccessEvaluationResult.Create( successResult.InspectionContext, successResult.StackFrame, item.Name, // Name - Left column successResult.FullName, successResult.Flags, successResult.Value, // Value - Middle column successResult.EditableValue, successResult.Type, // Type - Right column category, successResult.Access, successResult.StorageType, successResult.TypeModifierFlags, successResult.Address, successResult.CustomUIVisualizers, successResult.ExternalModules, successResult.RefreshButtonText, dataItem); } } else { result = DkmSuccessEvaluationResult.Create( visualizedExpression.InspectionContext, visualizedExpression.StackFrame, item.Name, // Name - Left column fullName, // FullName - What is being copied when "Add to watch" DkmEvaluationResultFlags.ReadOnly | (item.IsExpandable ? DkmEvaluationResultFlags.Expandable : DkmEvaluationResultFlags.None), item.ValueString, // Value - Middle column "", item.Type ?? "", // Type - Right column category, DkmEvaluationResultAccessType.None, DkmEvaluationResultStorageType.None, DkmEvaluationResultTypeModifierFlags.None, null, VSUIVisualizerService.GetUIVisualizers(item), null, null); dataItem = new VSCustomVisualizerEvaluator(result, item); } items[i] = DkmChildVisualizedExpression.Create( visualizedExpression.InspectionContext, visualizedExpression.VisualizerId, visualizedExpression.SourceId, visualizedExpression.StackFrame, valueHome, result, visualizedExpression, (uint)(startIndex + i), dataItem); } }
protected void EvaluateExpressionResult() { // We're going to customize the unexpanded display string, as well as the expanded // view (if requested later). // @TODO: Really don't understand why, but when we invoke the default eval below, and we get // reentrant calls for child member UObjects, they are coming back as root expressions // with an empty FullName. This subsequently fails to evaluate if we pass it through to // default eval again. Perhaps this is somehow related to breaking the potential infinite // recursion of visualizing children in order to visualize the parent, but don't follow how it // it supposed to be dealt with. if (expression_.TagValue == DkmVisualizedExpression.Tag.RootVisualizedExpression) { var as_root = expression_ as DkmRootVisualizedExpression; if (as_root.FullName.Length == 0) { string display_str = "{...}"; eval_ = DkmSuccessEvaluationResult.Create( expression_.InspectionContext, expression_.StackFrame, as_root.Name, as_root.Name, DkmEvaluationResultFlags.ReadOnly, display_str, "", #if !VS2013 as_root.Type, #else "Unknown", #endif DkmEvaluationResultCategory.Other, DkmEvaluationResultAccessType.None, DkmEvaluationResultStorageType.None, DkmEvaluationResultTypeModifierFlags.None, null, null, null, null ); state_ = EvaluationState.MinimalEvaluation; return; } } // string custom_display_str = Resources.UE4PropVis.IDS_DISP_CONDENSED; DkmSuccessEvaluationResult proto_eval = null; bool is_pointer; bool is_null; string address_str = ""; // @NOTE: Initially here we were executing the full default evaluation of our expression. // Problem is that this will call back into us for all UObject children of the expression, // because it needs to generate a visualization for them in order to construct its {member vals...} display string. // And then, we just ignore that anyway and display our own... // The following attempts to avoid that by casting our expression to void* and then evaluating that. // If it fails, we assume we are non-pointer. If it succeeds, we can determine from the result whether we are null or not. // @WARNING: This may not be so safe, since we can't determine whether evaluation failed because we tried to cast a non-pointer // to void*, or because the passed in expression was not valid in the first place. Believe we should be okay, since we should // only be receiving expressions that have already been determined to be suitable for our custom visualizer. // Ideally though, we'd be able to get a raw expression evaluation, without any visualization taking place. // Seems there must be a way to do this, but looks like it requires using a different API... const bool UseVoidCastOptimization = true; string default_expr_str = Utility.GetExpressionFullName(expression_); if (UseVoidCastOptimization) { default_expr_str = ExpressionManipulator.FromExpression(default_expr_str).PtrCast(Cpp.Void).Expression; } DkmEvaluationResult eval = DefaultEE.DefaultEval(default_expr_str, expression_, true); if (!UseVoidCastOptimization) { if (eval.TagValue != DkmEvaluationResult.Tag.SuccessResult) { // Genuine failure to evaluate the passed in expression eval_ = eval; state_ = EvaluationState.Failed; return; } else { proto_eval = (DkmSuccessEvaluationResult)eval; custom_display_str = proto_eval.Value; is_pointer = IsPointer(proto_eval); is_null = is_pointer && IsPointerNull(proto_eval); // @TODO: need to extract address string } } else { DkmDataAddress address = null; if (eval.TagValue != DkmEvaluationResult.Tag.SuccessResult) { // Assume the failure just implies the expression was non-pointer (thereby assuming that it was itself valid!) // @TODO: Could actually fall back onto standard evaluation here, in order to determine for sure // that the original expression is valid. Failure wouldn't be common since most of the time we are // dealing with pointer expressions, so any potential optimization should still be gained. is_pointer = false; is_null = false; } else { var success = (DkmSuccessEvaluationResult)eval; Debug.Assert(IsPointer(success)); is_pointer = true; is_null = is_pointer && IsPointerNull(success); address = success.Address; address_str = success.Value; } proto_eval = DkmSuccessEvaluationResult.Create( expression_.InspectionContext, expression_.StackFrame, "", "", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable, "", "", #if !VS2013 Utility.GetExpressionType(expression_), #else is_pointer ? "UObject *" : "UObject", #endif DkmEvaluationResultCategory.Other, DkmEvaluationResultAccessType.None, DkmEvaluationResultStorageType.None, DkmEvaluationResultTypeModifierFlags.None, address, null, null, null ); } string obj_expression_str = Utility.GetExpressionFullName(expression_); var obj_em = ExpressionManipulator.FromExpression(obj_expression_str); // Store pointer flags on the expression expression_.SetDataItem( DkmDataCreationDisposition.CreateAlways, new UObjectDataItem(is_pointer, is_null) ); if (!is_pointer) { // All subsequent manipulations of the expression assume it starts as a pointer to a // UObject-derived class, so if our expression is to a dereferenced UObject, just // prefix an 'address of' to the expression string. obj_em = obj_em.AddressOf(); } // Generate the condensed display string. if (is_null) { if (Config.CustomNullObjectPreview) { custom_display_str = "<NULL> UObject"; } else { var null_eval = DefaultEE.DefaultEval("(void*)0", expression_, true) as DkmSuccessEvaluationResult; custom_display_str = null_eval.Value + " <NULL>"; } } else if (Config.DisplayUObjectPreview) { // Prefix the address, if this is a pointer expression string address_prefix_str = ""; if (is_pointer) { address_prefix_str = address_str + " "; } // Specialized display for UClass? bool uclass_specialized = false; if (Config.DisplaySpecializedUClassPreview) { var uclass_em = obj_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjClass); var _uclass_fname_expr_str = uclass_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression; string _obj_uclass_name_str = UE4Utility.GetFNameAsString(_uclass_fname_expr_str, expression_); // @TODO: To simplify and for performance reasons, just hard coding known UClass variants if (_obj_uclass_name_str == "Class" || _obj_uclass_name_str == "BlueprintGeneratedClass" || _obj_uclass_name_str == "WidgetBlueprintGeneratedClass") { var fname_expr_str = obj_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression; string obj_name_str = UE4Utility.GetFNameAsString(fname_expr_str, expression_); var parent_uclass_fname_expr_str = obj_em.PtrCast(Typ.UStruct).PtrMember(Memb.SuperStruct).PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression; // This will return null if lookup failed for any reason. // We'll assume this meant no super class exists (ie. we're dealing with UClass itself) string parent_uclass_name_str = UE4Utility.GetFNameAsString(parent_uclass_fname_expr_str, expression_); if (parent_uclass_name_str == null) { parent_uclass_name_str = "None"; } custom_display_str = String.Format( "{0}{{ClassName='{1}', Parent='{2}'}}", address_prefix_str, obj_name_str, parent_uclass_name_str ); uclass_specialized = true; } } if (!uclass_specialized) { // For standard UObject condensed display string, show the object FName and its UClass. // @TODO: The evaluations required for this may be a performance issue, since they'll be done for all UObject children of any default visualized // aggregate type, even when it is not expanded (the default behaviour is to create a {...} display list of child member visualizations). var fname_expr_str = obj_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression; string obj_name_str = UE4Utility.GetFNameAsString(fname_expr_str, expression_); var uclass_fname_expr_str = obj_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjClass).PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression; string obj_uclass_name_str = UE4Utility.GetFNameAsString(uclass_fname_expr_str, expression_); custom_display_str = String.Format( "{0}{{Name='{1}', Class='{2}'}}", address_prefix_str, obj_name_str, obj_uclass_name_str ); } } eval_ = DkmSuccessEvaluationResult.Create( proto_eval.InspectionContext, proto_eval.StackFrame, // Override the eval name with the original expression name, since it will // have inherited the ",!" suffix. Utility.GetExpressionName(expression_), Utility.GetExpressionFullName(expression_), proto_eval.Flags, custom_display_str, //success_eval.Value, proto_eval.EditableValue, proto_eval.Type, proto_eval.Category, proto_eval.Access, proto_eval.StorageType, proto_eval.TypeModifierFlags, proto_eval.Address, proto_eval.CustomUIVisualizers, proto_eval.ExternalModules, null ); state_ = EvaluationState.Evaluated; }
private void GetRootResultAndContinue(DkmClrValue value, DkmWorkList workList, DkmClrType declaredType, DkmInspectionContext inspectionContext, string resultName, CompletionRoutine <DkmEvaluationResult> completionRoutine) { var type = value.Type.GetLmrType(); if (type.IsTypeVariables()) { var expansion = new TypeVariablesExpansion(type); var dataItem = new EvalResultDataItem( ExpansionKind.Default, resultName, typeDeclaringMember: null, declaredType: type, parent: null, value: value, displayValue: null, expansion: expansion, childShouldParenthesize: false, fullName: null, childFullNamePrefixOpt: null, formatSpecifiers: Formatter.NoFormatSpecifiers, category: DkmEvaluationResultCategory.Data, flags: DkmEvaluationResultFlags.ReadOnly, editableValue: null, inspectionContext: inspectionContext); Debug.Assert(dataItem.Flags == (DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable)); // Note: We're not including value.EvalFlags in Flags parameter // below (there shouldn't be a reason to do so). completionRoutine(DkmSuccessEvaluationResult.Create( InspectionContext: inspectionContext, StackFrame: value.StackFrame, Name: Resources.TypeVariablesName, FullName: dataItem.FullName, Flags: dataItem.Flags, Value: "", EditableValue: null, Type: "", Category: dataItem.Category, Access: value.Access, StorageType: value.StorageType, TypeModifierFlags: value.TypeModifierFlags, Address: value.Address, CustomUIVisualizers: null, ExternalModules: null, DataItem: dataItem)); } else { if ((inspectionContext.EvaluationFlags & DkmEvaluationFlags.ResultsOnly) != 0) { CreateEvaluationResultAndContinue( ResultsViewExpansion.CreateResultsOnlyRow(inspectionContext, resultName, declaredType, value, null, this.Formatter), workList, inspectionContext, value.StackFrame, completionRoutine); } else { ReadOnlyCollection <string> formatSpecifiers; var fullName = this.Formatter.TrimAndGetFormatSpecifiers(resultName, out formatSpecifiers); var dataItem = CreateDataItem( inspectionContext, resultName, typeDeclaringMember: null, declaredType: declaredType.GetLmrType(), value: value, parent: null, expansionFlags: ExpansionFlags.All, childShouldParenthesize: this.Formatter.NeedsParentheses(fullName), fullName: fullName, formatSpecifiers: formatSpecifiers, category: DkmEvaluationResultCategory.Other, flags: value.EvalFlags, evalFlags: inspectionContext.EvaluationFlags); GetResultAndContinue(dataItem, workList, declaredType, inspectionContext, parent: null, completionRoutine: completionRoutine); } } }
public void EvaluateVisualizedExpression(DkmVisualizedExpression visualizedExpression, out DkmEvaluationResult resultObject) { var rootExpr = visualizedExpression as DkmRootVisualizedExpression; if (rootExpr == null) { Debug.Fail("PythonViewNativeVisualizer.EvaluateVisualizedExpression was given a visualized expression that is not a DkmRootVisualizedExpression."); throw new NotSupportedException(); } DkmEvaluationResult rawResult; RawEvaluationResultHolder rawResultHolder; using (var rawExpr = DkmLanguageExpression.Create(CppExpressionEvaluator.CppLanguage, DkmEvaluationFlags.ShowValueRaw, rootExpr.FullName + ",!", null)) { rootExpr.EvaluateExpressionCallback(rootExpr.InspectionContext, rawExpr, rootExpr.StackFrame, out rawResult); rawResultHolder = new RawEvaluationResultHolder { RawResult = rawResult }; rootExpr.SetDataItem(DkmDataCreationDisposition.CreateAlways, rawResultHolder); } var rawSuccessResult = rawResult as DkmSuccessEvaluationResult; if (rawSuccessResult != null) { resultObject = DkmSuccessEvaluationResult.Create( rawResult.InspectionContext, rawResult.StackFrame, rootExpr.Name, rawSuccessResult.FullName, rawSuccessResult.Flags, rawSuccessResult.Value, rawSuccessResult.EditableValue, rawSuccessResult.Type, rawSuccessResult.Category, rawSuccessResult.Access, rawSuccessResult.StorageType, rawSuccessResult.TypeModifierFlags, rawSuccessResult.Address, rawSuccessResult.CustomUIVisualizers, rawSuccessResult.ExternalModules, rawResultHolder); return; } var rawFailedResult = rawResult as DkmFailedEvaluationResult; if (rawFailedResult != null) { resultObject = DkmFailedEvaluationResult.Create( rawResult.InspectionContext, rawResult.StackFrame, rootExpr.Name, rootExpr.FullName, rawFailedResult.ErrorMessage, rawFailedResult.Flags, rawResultHolder); return; } Debug.Fail("Raw evaluation result was neither DkmSuccessEvaluationResult nor DkmFailedEvaluationResult."); throw new NotSupportedException(); }
/// <summary> /// Evaluates visual expression and converts it to result visualizer. /// </summary> private void Evaluate() { if (VisualizedExpression.TagValue == DkmVisualizedExpression.Tag.RootVisualizedExpression) { DkmRootVisualizedExpression rootVisualizedExpression = VisualizedExpression as DkmRootVisualizedExpression; int processId = rootVisualizedExpression.InspectionSession?.Process?.LivePart?.Id ?? 0; string moduleName = rootVisualizedExpression.Module?.Name; string typeString = rootVisualizedExpression.Type; ulong address = 0; bool hasAddress = false; if (VisualizedExpression.ValueHome.TagValue == DkmExpressionValueHome.Tag.PointerValueHome) { address = (VisualizedExpression.ValueHome as DkmPointerValueHome).Address; hasAddress = true; } if (string.IsNullOrEmpty(typeString) || string.IsNullOrEmpty(moduleName) || !hasAddress) { string displayString = "{...CsDebugScript failure...}"; EvaluationResult = DkmSuccessEvaluationResult.Create( VisualizedExpression.InspectionContext, VisualizedExpression.StackFrame, rootVisualizedExpression.Name, rootVisualizedExpression.FullName, DkmEvaluationResultFlags.ReadOnly, displayString, "", rootVisualizedExpression.Type, DkmEvaluationResultCategory.Other, DkmEvaluationResultAccessType.None, DkmEvaluationResultStorageType.None, DkmEvaluationResultTypeModifierFlags.None, null, null, null, null); return; } string title; try { Process process = Process.All.First(p => p.SystemId == processId); Module module = process.ModulesByName[System.IO.Path.GetFileNameWithoutExtension(moduleName)]; CodeType codeType = ResolveCodeType(process, module, typeString); Variable = codeType.IsPointer ? Variable.CreatePointer(codeType, address) : Variable.Create(codeType, address); title = Variable.ToString(); ResultVisualizer = CsDebugScript.UI.ResultVisualizers.ResultVisualizer.Create(Variable, Variable.GetType(), "result", CompletionDataType.Unknown, dummyInteractiveResultVisualizer); } catch { title = "{...CsDebugScript...}"; } DkmDataAddress dkmDataAddress = DkmDataAddress.Create(VisualizedExpression.RuntimeInstance, address, rootVisualizedExpression.StackFrame?.InstructionAddress); EvaluationResult = DkmSuccessEvaluationResult.Create( VisualizedExpression.InspectionContext, VisualizedExpression.StackFrame, rootVisualizedExpression.Name, rootVisualizedExpression.FullName, DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable, title, "", rootVisualizedExpression.Type, DkmEvaluationResultCategory.Other, DkmEvaluationResultAccessType.None, DkmEvaluationResultStorageType.None, DkmEvaluationResultTypeModifierFlags.None, dkmDataAddress, VSUIVisualizerService.GetUIVisualizers(ResultVisualizer), null, null); return; } // This should never happen... throw new NotImplementedException(); }
public override void GetChildItems(DkmEvaluationResultEnumContext enumContext, int start, int count, out DkmChildVisualizedExpression[] items) { // Cap the requested number to the total remaining from startIndex count = Math.Min(count, enumContext.Count - start); items = new DkmChildVisualizedExpression[count]; uint idx = 0; // Retrieve the default expansion enum context var default_data = enumContext.GetDataItem <DefaultEnumContextDataItem>(); if (start < default_data.Context.Count) { // Requesting default children int default_count = Math.Min(count, default_data.Context.Count - start); DkmEvaluationResult[] default_evals; expression_.GetItemsCallback(default_data.Context, start, default_count, out default_evals); for (int dft_idx = 0; dft_idx < default_count; ++dft_idx, ++idx) { DkmSuccessEvaluationResult success_eval = default_evals[dft_idx] as DkmSuccessEvaluationResult; DkmExpressionValueHome home = null; if (success_eval != null && success_eval.Address != null) { home = DkmPointerValueHome.Create(success_eval.Address.Value); } else { home = DkmFakeValueHome.Create(0); } items[idx] = DkmChildVisualizedExpression.Create( enumContext.InspectionContext, expression_.VisualizerId, // @TODO: Check this is what we want. Will we get callbacks for it, regardless of its type? expression_.SourceId, enumContext.StackFrame, home, default_evals[dft_idx], expression_, (uint)start, null ); } } if (start + count > default_data.Context.Count) { // Requesting custom children // @NOTE: Currently just assuming only 1 custom child (prop list) and hard coding as such. // DkmSuccessEvaluationResult.ExtractFromProperty(IDebugProperty3!!!!!!!) ............................................... // @NOTE: Had thought could just create an expression with a null evaluation // inside it, and by giving it a visualizer guid, the system would call back // to us to evaluate the expression. Seems not to work though, I guess because the // visualizer guid identifies the visualizer but not the containing component, // and since the expression itself doesn't have a type, it can't know that it // should call our component. DkmEvaluationResult eval = DkmSuccessEvaluationResult.Create( enumContext.InspectionContext, enumContext.StackFrame, Resources.UE4PropVis.IDS_DISP_BLUEPRINTPROPERTIES, Resources.UE4PropVis.IDS_DISP_BLUEPRINTPROPERTIES, DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable, "", // @TODO: something like "[<count> properties]" null, "", // Type column DkmEvaluationResultCategory.Other, DkmEvaluationResultAccessType.None, DkmEvaluationResultStorageType.None, DkmEvaluationResultTypeModifierFlags.None, null, null, null, null ); // This child is just for organization and does not correspond to anything in memory. DkmExpressionValueHome valueHome = DkmFakeValueHome.Create(0); var prop_list_expr = DkmChildVisualizedExpression.Create( enumContext.InspectionContext, Guids.Visualizer.PropertyList, // Associate the expression with ourselves, since we created it Guids.Component.VisualizerComponent, enumContext.StackFrame, valueHome, eval, expression_, idx, null ); // Create a visualizer for the property list, and attach it to the expression. var prop_list_visualizer = new PropertyListVisualizer(prop_list_expr, access_ctx_); prop_list_expr.SetDataItem(DkmDataCreationDisposition.CreateAlways, new ExpressionDataItem(prop_list_visualizer)); items[idx] = prop_list_expr; } }