Exemplo n.º 1
0
        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,
            });
        }