public IChildAdapter CreateForTesting(RemoteValue remoteValue, IRemoteValueFormat remoteValueFormat, VarInfoBuilder varInfoBuilder, string formatSpecifier, int maxCountPerRange) => RemoteValueRangedAdapter.First( maxCountPerRange, new RemoteValueChildAdapter(remoteValue, remoteValueFormat, varInfoBuilder, formatSpecifier));
public void SetUp() { mockFrame = Substitute.For <RemoteFrame>(); var childAdapterFactory = new RemoteValueChildAdapter.Factory(); var varInfoFactory = new LLDBVariableInformationFactory(childAdapterFactory); var varInfoBuilder = new VarInfoBuilder(varInfoFactory); varInfoFactory.SetVarInfoBuilder(varInfoBuilder); var registerSetsBuilderFactory = new RegisterSetsBuilder.Factory(varInfoFactory); registerSetsBuilder = registerSetsBuilderFactory.Create(mockFrame); generalPurposeRegisters = Substitute.For <RemoteValue>(); generalPurposeRegisters.GetName().Returns("General Purpose Registers"); generalPurposeRegisters.GetNumChildren().Returns(0u); floatingPointRegisters = Substitute.For <RemoteValue>(); floatingPointRegisters.GetName().Returns("Floating Point Registers"); floatingPointRegisters.GetNumChildren().Returns(3u); xmm0 = Substitute.For <RemoteValue>(); xmm0.GetName().Returns("xmm0"); xmm8 = Substitute.For <RemoteValue>(); xmm8.GetName().Returns("xmm8"); other = Substitute.For <RemoteValue>(); other.GetName().Returns("other"); floatingPointRegisters.GetChildren(0, 3).Returns( new List <RemoteValue>() { xmm0, xmm8, other }); }
private IEnumerable <IVariableInformation> BuildSyntheticSets() { RemoteValue floatingPointRegs = frame.GetRegisters() .Where(r => r.GetName() == floatingPointRegistersSetName) .FirstOrDefault(); if (floatingPointRegs == null) { return(Enumerable.Empty <IVariableInformation>()); } var sets = new List <IVariableInformation>(); // A preset Natvis entry for CustomVisualizer.SSE shows the registers xmm<0-7> // contained in the floating point register set as VectorOfFloat32. sets.Add(varInfoFactory.Create(floatingPointRegs, "SSE", customVisualizer: CustomVisualizer.SSE)); // A preset Natvis entry for CustomVisualizer.SSE2 shows the registers xmm<0-15> // contained in the floating point register set as VectorOfFloat64, and xmm<8-15> as // VectorOfFloat32. sets.Add(varInfoFactory.Create(floatingPointRegs, "SSE2", customVisualizer: CustomVisualizer.SSE2)); return(sets); }
public async Task LldbEvalWithContextVarsAsync() { _optionPageGrid.ExpressionEvaluationEngine = ExpressionEvaluationEngineFlag.LLDB_EVAL_WITH_FALLBACK; RemoteValue mockVariable = CreateMockVariable(); var natvisScope = new NatvisScope(); var contextVar = RemoteValueFakeUtil.CreateSimpleInt("var", 14); natvisScope.AddScopedName("var", "$var_0"); natvisScope.AddContextVariable("$var_0", contextVar); await _evaluator.EvaluateExpressionAsync( "2 + var", _varInfoFactory.Create(mockVariable), natvisScope, "result"); await mockVariable.Received(1).EvaluateExpressionLldbEvalAsync( Arg.Is("2 + $var_0"), Arg.Is(natvisScope.ContextVariables)); Assert.That(natvisScope.ContextVariables.Count, Is.EqualTo(1)); Assert.That(natvisScope.ContextVariables.ContainsKey("$var_0")); Assert.That(natvisScope.ContextVariables["$var_0"], Is.EqualTo(contextVar)); await mockVariable.DidNotReceive().EvaluateExpressionAsync(Arg.Any <string>()); }
static IEnumerable <RemoteValue> GetRemoteValueChildren(RemoteValue remoteValue, int offset, int count) { var result = new List <RemoteValue>(); uint childOffset = (uint)offset; uint endIndex = (uint)(offset + count); uint numChildren = remoteValue.GetNumChildren(); while (childOffset < endIndex) { // Fetch children in batches for performance reasons. uint batchSize = System.Math.Min(endIndex - childOffset, _maxChildBatchSize); List <RemoteValue> currentBatch = remoteValue.GetChildren(childOffset, batchSize); for (int n = 0; n < batchSize; ++n) { RemoteValue childValue = currentBatch[n]; if (childValue != null) { result.Add(childValue); } else if (n + childOffset < numChildren) { // There were times when LLDB was returning an error and thus a null child // value. ex: Children[1] for a CustomType&* type. Trace.WriteLine( $"WARNING: No child found at index {n + childOffset} of " + $"({remoteValue.GetTypeName()}){remoteValue.GetFullName()} even " + $"though there are {numChildren} children."); } } childOffset += batchSize; } return(result); }
/// <summary> /// Get the variable assignment expression as a string. Returns null if the value is /// constant or invalid. /// </summary> public static string GetVariableAssignExpression(this RemoteValue remoteValue) { var valueType = remoteValue.GetValueType(); if (valueType == ValueType.Invalid) { return(null); } if (valueType == ValueType.Register) { return($"${remoteValue.GetName()}"); } TypeFlags?typeFlags = remoteValue.GetTypeInfo()?.GetTypeFlags(); if (typeFlags.HasValue && typeFlags.Value.HasFlag(TypeFlags.IS_ARRAY)) { return(null); } string variableExpression = remoteValue.GetFullName(); if (variableExpression == null) { variableExpression = remoteValue.GetMemoryAddressAssignExpression(); } return(variableExpression); }
/// <summary> /// Returns the address to be used as memory context. This is used to get an address /// from an expression entered into Visual Studio's memory view's address text box. /// </summary> public static ulong?GetMemoryContextAddress(this RemoteValue remoteValue) { if (!IsValidValue(remoteValue)) { return(null); } TypeFlags GetTypeFlags(RemoteValue value) => remoteValue.GetTypeInfo().GetCanonicalType().GetTypeFlags(); // If the value is an array, try to obtain its address. TypeFlags flags = GetTypeFlags(remoteValue); if (flags.HasFlag(TypeFlags.IS_ARRAY)) { remoteValue = remoteValue.AddressOf(); if (!IsValidValue(remoteValue)) { return(null); } flags = GetTypeFlags(remoteValue); } // Only interpret pointers, references and integers as addresses. if (!flags.HasFlag(TypeFlags.IS_REFERENCE) && !flags.HasFlag(TypeFlags.IS_POINTER) && !flags.HasFlag(TypeFlags.IS_INTEGER)) { return(null); } return(remoteValue.GetValueAsUnsigned()); }
public bool Assign(string expression, out string error) { if (IsReadOnly) { error = string.Format( "Attempted to assign a value to a read only variable with name '{0}'.", DisplayName); return(false); } string cast = ""; if (_remoteValue.TypeIsPointerType() || _remoteValue.GetTypeInfo().GetTypeFlags().HasFlag(TypeFlags.IS_ENUMERATION)) { cast = $"({_remoteValue.GetTypeInfo().GetCanonicalType().GetName()})"; } expression = _remoteValueFormat.FormatExpressionForAssignment(_remoteValue, expression); // Avoid using parentheses to enclose registers because they can prevent assignments // involving initialization lists from succeeding. if (_remoteValue.GetValueType() != DebuggerApi.ValueType.Register) { expression = $"({expression})"; } RemoteValue tempValue = _remoteValue.CreateValueFromExpression( DisplayName, $"{_remoteValue.GetVariableAssignExpression()} = {cast}{expression}"); SbError sbError = tempValue.GetError(); error = sbError.Fail() ? sbError.GetCString() : null; return(sbError.Success()); }
internal static GrpcSbValue CreateValue(RemoteValue remoteValue, long id) => new GrpcSbValue { Id = id, Name = remoteValue.GetName() ?? "", Error = CreateError(remoteValue.GetError()) };
// TODO: handle the situation when raw and expand formatter are both present public virtual IVariableInformation Create( RemoteValue remoteValue, string displayName = null, FormatSpecifier formatSpecifier = null, CustomVisualizer customVisualizer = CustomVisualizer.None) { IVariableInformation varInfo = _varInfoFactory.Create(remoteValue, displayName, formatSpecifier, customVisualizer); // Don't use Natvis for raw format specifier (!), e.g. "myvar,!". if (FormatSpecifierUtil.HasRawFormatSpecifier(varInfo.FormatSpecifier)) { return(new CachingVariableInformation(varInfo)); } var natvisVarInfo = new NatvisVariableInformation(_natvisExpander, varInfo); if (ExpandFormatSpecifierUtil.TryParseExpandFormatSpecifier( natvisVarInfo.FormatSpecifier, out int expandedIndex)) { return(new CachingVariableInformation( _expandVariableFactory.Create(natvisVarInfo, expandedIndex))); } return(new CachingVariableInformation(natvisVarInfo)); }
static IEnumerable <RemoteValue> GetPointerChildren(RemoteValue value, int offset, int count) { var result = new List <RemoteValue>(); SbType pointeeType = value.GetTypeInfo()?.GetPointeeType(); if (pointeeType == null) { // If we cannot get the pointee type, just return the empty list. return(result); } ulong byteSize = pointeeType.GetByteSize(); ulong baseAddress = value.GetValueAsUnsigned() + (ulong)offset * byteSize; for (int n = 0; n < count; ++n) { ulong address = baseAddress + (ulong)n * byteSize; RemoteValue childValue = value.CreateValueFromAddress($"[{offset + n}]", address, pointeeType); if (childValue != null) { result.Add(childValue); } } return(result); }
public RemoteValueVariableInformation CreateVarInfo( RemoteValue remoteValue, string displayName) { return(new RemoteValueVariableInformation(varInfoBuilder, "", RemoteValueFormat.Default, ValueFormat.Default, remoteValue, displayName, CustomVisualizer.None, childAdapterFactory)); }
private GrpcValueInfo CreateValueInfoAndUpdateStores(RemoteValue remoteValue) { if (remoteValue == null) { return(null); } string expressionPath; var hasExpressionPath = remoteValue.GetExpressionPath(out expressionPath); var valueInfo = new GrpcValueInfo { ExpressionPath = expressionPath ?? "", HasExpressionPath = hasExpressionPath, NumChildren = remoteValue.GetNumChildren(), Summary = remoteValue.GetSummary() ?? "", TypeName = remoteValue.GetTypeName() ?? "", Value = remoteValue.GetValue() ?? "", ValueType = EnumUtil.ConvertTo <Debugger.Common.ValueType>( remoteValue.GetValueType()), IsPointerType = remoteValue.TypeIsPointerType(), ByteSize = remoteValue.GetByteSize(), }; var typeInfo = remoteValue.GetTypeInfo(); if (typeInfo != null) { valueInfo.Type = GrpcFactoryUtils.CreateType( typeInfo, typeStore.AddObject(typeInfo)); } return(valueInfo); }
public RemoteValue GetCachedView(DebuggerApi.ValueFormat format) { GetCachedViewResponse response = null; if (connection.InvokeRpc(() => { response = client.GetCachedView( new GetCachedViewRequest { Value = grpcSbValue, Format = format.ConvertTo <Debugger.Common.ValueFormat>() }); })) { if (response.ValueInfo != null) { RemoteValue addressOf = null; if (response.AddressValue != null && response.AddressValue.Id != 0) { addressOf = valueFactory.Create(connection, response.AddressValue); if (response.AddressInfo != null) { // gRpc server does not set |format| on |addressOf|, so use default. addressOf = CreateCachedValue(addressOf, response.AddressInfo, null, DebuggerApi.ValueFormat.Default); } } return(CreateCachedValue(this, response.ValueInfo, addressOf, format)); } } return(null); }
public override Task <GetChildrenResponse> GetChildren( GetChildrenRequest request, ServerCallContext context) { var value = valueStore.GetObject(request.Value.Id); var children = value.GetChildren(request.Offset, request.Count); var response = new GetChildrenResponse(); for (uint n = 0; n < children.Count; ++n) { RemoteValue child = children[(int)n]; if (child != null) { response.Children[n + request.Offset] = GrpcFactoryUtils.CreateValue(child, valueStore.AddObject(child)); } } // (internal): Special case for pointers. LLDB names them $"*{value.GetName()}", but // Visual Studio just shows an empty name. if (value.TypeIsPointerType() && response.Children.ContainsKey(0) && response.Children[0].Name == $"*{value.GetName()}") { response.Children[0].Name = string.Empty; } return(Task.FromResult(response)); }
public virtual RemoteValue Create(RemoteValue remoteProxy, RemoteValue addressOf, SbType typeInfo, string expressionPath, bool hasExpressionPath, uint numChildren, string summary, string typeName, string value, ValueType valueType, bool isPointerType, ValueFormat valueFormat, ulong byteSize) => new CachedValue(remoteProxy, addressOf, typeInfo, expressionPath, hasExpressionPath, numChildren, summary, typeName, value, valueType, isPointerType, valueFormat, byteSize);
public async Task <EvaluationResult> EvaluateExpressionAsync() { VsExpression vsExpression = await _vsExpressionCreator.CreateAsync(_text, EvaluateSizeSpecifierExpressionAsync); IDebugProperty2 result; if (vsExpression.Value.StartsWith(".")) { EvaluateCommand(vsExpression.Value, out result); return(EvaluationResult.FromResult(result)); } RemoteValue remoteValue = await CreateValueFromExpressionAsync(vsExpression.Value); if (remoteValue == null) { return(EvaluationResult.Fail()); } string displayName = vsExpression.ToString(); IVariableInformation varInfo = _varInfoBuilder.Create(remoteValue, displayName, vsExpression.FormatSpecifier); result = _createPropertyDelegate.Invoke(varInfo); return(EvaluationResult.FromResult(result)); }
/// <summary> /// Returns an unquoted, unescaped version of the result from FormatValue() if that value /// looks like a quoted and escaped string literal. For instance, L"\"foo\\nbar\"" becomes /// "foo\nbar". Returns "" otherwise. /// </summary> public virtual string FormatStringView( RemoteValue remoteValue, ValueFormat fallbackValueFormat) { string value = FormatValue(remoteValue, fallbackValueFormat); return(CStringEscapeHelper.Unescape(value)); }
RemoteValue CreateMockVariable() { RemoteValue mockVariable = Substitute.For <RemoteValue>(); mockVariable.TypeIsPointerType().Returns(false); mockVariable.GetValueForExpressionPath(Arg.Any <string>()).Returns((RemoteValue)null); return(mockVariable); }
public virtual uint GetNumChildren(RemoteValue remoteValue) { if (_sizeSpecifier is uint childCount) { return(GetNumPointerOrArrayChildren(childCount, remoteValue)); } return(remoteValue.GetNumChildren()); }
public void Pointer() { RemoteValue remoteValue = RemoteValueFakeUtil.CreatePointer("dummyType*", "dummyName", "0xDEADC0DE"); Assert.That(RemoteValueExtensions.GetMemoryContextAddress(remoteValue), Is.EqualTo(0xDEADC0DE)); }
RemoteValueChildAdapter(RemoteValue remoteValue, IRemoteValueFormat remoteValueFormat, VarInfoBuilder varInfoBuilder, string formatSpecifier) { _remoteValue = remoteValue; _remoteValueFormat = remoteValueFormat; _varInfoBuilder = varInfoBuilder; _formatSpecifier = formatSpecifier; }
public string FormatValueWithSize(RemoteValue remoteValue, uint size) { string result = GetValueAsString(remoteValue, size, out string error); if (result == null) { return(error); } return(CStringEscapeHelper.Escape(result, _prefix, _postfix)); }
public virtual string FormatExpressionForAssignment( RemoteValue remoteValue, string expression) { if (remoteValue.GetTypeInfo().GetTypeFlags().HasFlag(TypeFlags.IS_FLOAT)) { return(FloatRadixConversionHelper.TryConvertToFloatFromNumberString( expression, new System.Lazy <int>(() => (int)remoteValue.GetByteSize()))); } return(expression); }
public virtual string FormatValueAsAddress(RemoteValue remoteValue) { TypeFlags flags = remoteValue?.GetTypeInfo()?.GetTypeFlags() ?? 0; if (flags.HasFlag(TypeFlags.IS_REFERENCE) || flags.HasFlag(TypeFlags.IS_POINTER)) { return($"0x{remoteValue.GetValueAsUnsigned():x16}"); } return(string.Empty); }
/// <summary> /// Returns |remoteValue|'s summary if present and its value otherwise, formatted using /// |valueFormat|. /// </summary> public static string GetDisplayValue(this RemoteValue remoteValue, ValueFormat valueFormat) { var strValue = remoteValue.GetSummary(valueFormat); if (!string.IsNullOrEmpty(strValue)) { return(TryConvertToUtf8(strValue)); } return(remoteValue.GetValue(valueFormat)); }
public async Task <IVariableInformation> EvaluateExpressionAsync(string displayName, VsExpression vsExpression) { RemoteValue resultValue = await _remoteValue.EvaluateExpressionAsync(vsExpression.Value); return(resultValue == null ? null : _varInfoBuilder.Create(resultValue, displayName, formatSpecifier: vsExpression.FormatSpecifier)); }
public IVariableInformation FindChildByName(string name) { RemoteValue child = _remoteValue.GetChildMemberWithName(name); if (child == null) { return(null); } return(_varInfoBuilder.Create(child, name)); }
public void AddValueFromExpression(string expression, RemoteValue value) { Queue <RemoteValue> values; if (!expressionValues.TryGetValue(expression, out values)) { values = new Queue <RemoteValue>(); expressionValues[expression] = values; } values.Enqueue(value); }
/// <summary> /// Return the expression path of the remoteValue. Don't return LLDB scratch variables like /// "$23" because they sometimes don't behave as expected when assigning values to them /// and they don't persist across debug sessions correctly. /// </summary> public static string GetFullName(this RemoteValue remoteValue) { string expressionPath; if (remoteValue.GetExpressionPath(out expressionPath) && !string.IsNullOrEmpty(expressionPath) && !expressionPath.Contains("$")) { return(expressionPath); } return(null); }