public QueueNode(ILiveWatchEngine engine, NodeSource root, QueueTypeDescriptor queue, IPinnedVariable variable, IPinnedVariableType queueType, string userFriendlyName) : base("$rtos.queue." + variable.UserFriendlyName) { _Engine = engine; _Descriptor = queue; _QueueType = queueType; _Root = root; if (_Descriptor.IsIndirect) { _PointerVariable = engine.CreateLiveVariable(variable); } else if (_Descriptor.TypeOverride != null) { _QueueVariable = engine.Symbols.CreateTypedVariable(variable.Address, engine.Symbols.LookupType(_Descriptor.TypeOverride, true)); } else { _QueueVariable = variable; } Name = userFriendlyName; RawType = _Descriptor.Type.ToString(); Capabilities = LiveWatchCapabilities.CanHaveChildren | LiveWatchCapabilities.CanPlotValue | LiveWatchCapabilities.CanSetBreakpoint; SelectedFormatter = engine.GetDefaultFormatter(ScalarVariableType.SInt32); Location = new LiveWatchPhysicalLocation(null, variable.SourceLocation.File, variable.SourceLocation.Line); }
public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context) { int estimatedStackSize = (int)(_StackEnd - _StackStart); if (_OverflowDetected) { return(ReportStackOverflow(estimatedStackSize)); } if (_Error != null) { return new LiveWatchNodeState { Icon = LiveWatchNodeIcon.Error, Value = _Error } } ; var rawValue = _BorderVariable?.GetValue() ?? default; if (!rawValue.IsValid || CountUnusedStackMarkers(rawValue.Value) != rawValue.Value.Length) { ulong lastKnownEndOfStack; if (_BorderVariable != null) { lastKnownEndOfStack = _BorderVariable.Address + (uint)_BorderVariable.Size; } else { lastKnownEndOfStack = _StackEnd; } _BorderVariable?.Dispose(); _BorderVariable = null; ulong startOfCheckedArea; if (!_StackOpposesGrowingHeap) { //Maximum size is fixed. No guessing needed. startOfCheckedArea = _StackStart; } else if (_HeapEndVariable != null) { //Stack immediately follows the dynamically growing heap startOfCheckedArea = _HeapEndVariable.GetValue().ToUlong(); if (startOfCheckedArea == 0) { startOfCheckedArea = _StackStart; //The heap has never been used yet } estimatedStackSize = (int)(_StackEnd - _StackStart); } else { //No heap. Stack directly follows the 'end' symbol. startOfCheckedArea = _StackStart; } int position = MeasureUnusedStackArea(startOfCheckedArea, lastKnownEndOfStack); if (position == 0) { _OverflowDetected = true; } else { _PatternEverFound = true; } if (_OverflowDetected) { return(ReportStackOverflow(estimatedStackSize)); } else { int watchSize = Math.Min(_MaxBorderVariableSize, position); _BorderVariable = _Engine.Memory.CreateLiveVariable(startOfCheckedArea + (uint)position - (uint)watchSize, watchSize); } } ulong firstUsedStackSlot = _BorderVariable.Address + (uint)_BorderVariable.Size; Location = new LiveWatchPhysicalLocation(firstUsedStackSlot, null, 0); int stackUsage = (int)(_StackEnd - firstUsedStackSlot); RawValue = new LiveVariableValue(rawValue.Timestamp, rawValue.Generation, BitConverter.GetBytes(stackUsage)); if (_HeapEndVariable != null) { var rawHeapEnd = _HeapEndVariable.GetValue(); ulong heapEnd = rawHeapEnd.ToUlong(); if (heapEnd == 0) { heapEnd = _StackStart; } estimatedStackSize = (int)(_StackEnd - heapEnd); _DistanceToHeapEnd = new LiveVariableValue(rawHeapEnd.Timestamp, rawHeapEnd.Generation, BitConverter.GetBytes((int)(firstUsedStackSlot - heapEnd))); } string text; if (estimatedStackSize > 0) { text = $"{stackUsage}/{estimatedStackSize} bytes"; } else { text = $"{stackUsage} bytes"; } if (context.PreloadChildren && _Children == null && _HeapEndVariable != null) { _Children = new ILiveWatchNode[] { new DistanceToHeapNode(this) }; } return(new LiveWatchNodeState { Value = text, Icon = LiveWatchNodeIcon.Stack, NewChildren = _Children, }); }