コード例 #1
0
ファイル: ThreadNodes.cs プロジェクト: mfkiwl/RTOSPlugins
 private LiveWatchNodeState ReportStackOverflow(int estimatedStackSize)
 {
     RawValue = new LiveVariableValue(DateTime.Now, LiveVariableValue.OutOfScheduleGeneration, BitConverter.GetBytes(estimatedStackSize));
     return(new LiveWatchNodeState {
         Icon = LiveWatchNodeIcon.Error, Value = _PatternEverFound ? "Stack overflow detected!" : $"Unused stack is not filled with 0x{_UnusedStackFillPatern}"
     });
 }
コード例 #2
0
ファイル: ThreadNodes.cs プロジェクト: mfkiwl/RTOSPlugins
            public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context)
            {
                var pxTopOfStack       = _ThreadNode._Variables.pxTopOfStackLive.GetValue();
                int estimatedStackSize = ProvideEstimatedStackSize(out var pxStack);

                long freeStackBytes = (long)(pxTopOfStack.ToUlong() - pxStack);

                //This will be negative if estimatedStackSize is unknown. It is by design to report that we don't know the exact size.
                RawValue = new LiveVariableValue(pxTopOfStack.Timestamp, pxTopOfStack.Generation, BitConverter.GetBytes(estimatedStackSize - freeStackBytes));

                if (estimatedStackSize == 0)
                {
                    return new LiveWatchNodeState {
                               Value = $"({freeStackBytes} bytes remaining)"
                    }
                }
                ;
                else
                {
                    return new LiveWatchNodeState {
                               Value = $"{estimatedStackSize - freeStackBytes}/{estimatedStackSize} bytes"
                    }
                };
            }
        }
コード例 #3
0
ファイル: HeapNodes.cs プロジェクト: mfkiwl/RTOSPlugins
            public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context)
            {
                int value = _Callback(_HeapNode._ParsedHeapContents);

                RawValue = new LiveVariableValue(_HeapNode._HeapContents.Timestamp, _HeapNode._HeapContents.Generation, BitConverter.GetBytes(value));
                return(new LiveWatchNodeState {
                    Value = SelectedFormatter.FormatValue(RawValue.Value)
                });
            }
コード例 #4
0
ファイル: ThreadNodes.cs プロジェクト: mfkiwl/RTOSPlugins
            public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context)
            {
                //This allows plotting the state of the thread as a regular int variable.
                RawValue = new LiveVariableValue(_ThreadNode._LastSeen, LiveVariableValue.OutOfScheduleGeneration, _ThreadNode.IsRunning ? True : False);

                return(new LiveWatchNodeState
                {
                    Value = _ThreadNode.IsRunning ? "1" : "0"
                });
            }
コード例 #5
0
ファイル: KernelNode.cs プロジェクト: mfkiwl/RTOSPlugins
            public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context)
            {
                var freeBytesValue = _Variable.GetValue();
                var freeBytes      = (int)freeBytesValue.ToUlong();

                int usedBytes = _HeapSize - freeBytes;

                RawValue = new LiveVariableValue(freeBytesValue.Timestamp, freeBytesValue.Generation, BitConverter.GetBytes(usedBytes));

                return(new LiveWatchNodeState
                {
                    Value = $"{usedBytes}/{_HeapSize} bytes"
                });
            }
コード例 #6
0
        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,
            });
        }
コード例 #7
0
ファイル: QueueNodes.cs プロジェクト: mfkiwl/RTOSPlugins
        public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context)
        {
            if (_PointerVariable != null)
            {
                var address = _PointerVariable.GetValue().ToUlong() & ~1UL;
                if (address != _QueueVariable?.Address)
                {
                    _QueueVariable = _Engine.Symbols.CreateTypedVariable(address, _QueueType);
                }
            }

            if (_QueueVariable != null && _QueueVariable.Address != _Variables.LastKnownAddress)
            {
                _Variables.LastKnownAddress = _QueueVariable.Address;

                //The previous instance will get auto-disposed by VisualGDB.
                _QueueObjectNode = null;
                _Variables.Reset();

                if (_QueueVariable.Address != 0)
                {
                    _Variables.uxMessagesWaiting = _Engine.CreateLiveVariable(_QueueVariable.LookupSpecificChild(nameof(_Variables.uxMessagesWaiting)));
                    _Variables.uxLength          = _Engine.CreateLiveVariable(_QueueVariable.LookupSpecificChild(nameof(_Variables.uxLength)));

                    _Variables.u_xSemaphore_xMutexHolder         = _Engine.CreateLiveVariable(_QueueVariable.LookupChildRecursively("u.xSemaphore.xMutexHolder"));
                    _Variables.u_xSemaphore_uxRecursiveCallCount = _Engine.CreateLiveVariable(_QueueVariable.LookupChildRecursively("u.xSemaphore.uxRecursiveCallCount"));
                }
            }

            if (context.PreloadChildren && _QueueVariable != null && _QueueObjectNode == null && _QueueVariable.Address != 0)
            {
                _QueueObjectNode = _Engine.CreateNodeForPinnedVariable(_QueueVariable, new LiveWatchNodeOverrides {
                    Name = "[Object]"
                });
            }

            var result = new LiveWatchNodeState();

            if ((_QueueVariable?.Address ?? 0) == 0)
            {
                result.Value = "[NULL]";
            }
            else if (_Variables.uxLength == null || _Variables.uxMessagesWaiting == null)
            {
                result.Value = "???";
            }
            else
            {
                if (_Descriptor.TypeOverride != null && !_StaticType.HasValue)
                {
                    var typeVar = _QueueVariable.LookupSpecificChild("ucQueueType");
                    if (typeVar != null)
                    {
                        _StaticType = (QueueType)_Engine.ReadMemory(typeVar).ToUlong();
                        RawType     = _StaticType.Value.ToString();
                    }
                }

                var detectedType = _StaticType ?? _Descriptor.Type;

                var   rawValue = _Variables.uxMessagesWaiting.GetValue();
                int   value = (int)rawValue.ToUlong();
                int   maxValue = (int)_Variables.uxLength.GetValue().ToUlong();
                ulong owner = 0, level = 0;

                if (detectedType != QueueType.BaseQueue && _Variables.u_xSemaphore_xMutexHolder != null && _Variables.u_xSemaphore_uxRecursiveCallCount != null)
                {
                    owner = _Variables.u_xSemaphore_xMutexHolder.GetValue().ToUlong();
                    level = _Variables.u_xSemaphore_uxRecursiveCallCount.GetValue().ToUlong();

                    if (owner == _QueueVariable.Address)
                    {
                        detectedType = QueueType.Semaphore;
                    }
                    else
                    {
                        detectedType = QueueType.RecursiveMutex;
                    }
                }

                if (detectedType == QueueType.RecursiveMutex || detectedType == QueueType.NonRecursiveMutex)
                {
                    if (value != 0)
                    {
                        result.Value = "free";
                        RawValue     = new LiveVariableValue(rawValue.Timestamp, rawValue.Generation, BitConverter.GetBytes(0));
                    }
                    else if (_Variables.u_xSemaphore_xMutexHolder != null && _Variables.u_xSemaphore_uxRecursiveCallCount != null)
                    {
                        string threadName = _Root.GetThreadName(owner);
                        result.Value = $"taken by {threadName}";
                        if (level >= 1)
                        {
                            result.Value += $" (recursion = {level})";
                        }

                        RawValue = new LiveVariableValue(rawValue.Timestamp, rawValue.Generation, BitConverter.GetBytes((int)level + 1));
                    }
                    else
                    {
                        result.Value = "taken";
                    }
                }
                else
                {
                    RawValue     = rawValue;
                    result.Value = $"{value}/{maxValue}";
                }

                result.NewType = detectedType.ToString();

                switch (detectedType)
                {
                case QueueType.BinarySemaphore:
                case QueueType.Semaphore:
                case QueueType.RecursiveMutex:
                case QueueType.NonRecursiveMutex:
                    result.Icon = LiveWatchNodeIcon.Flag;
                    break;

                case QueueType.BaseQueue:
                    result.Icon = LiveWatchNodeIcon.Queue;
                    break;
                }


                if (context.PreloadChildren)
                {
                    ProvideWaitingThreadsNodes(detectedType);
                    result.NewChildren = new[] { _ReadThreadQueue, _WriteThreadQueue, _QueueObjectNode }.Where(n => n != null).ToArray();
                }
            }

            return(result);
        }
コード例 #8
0
ファイル: ThreadNodes.cs プロジェクト: mfkiwl/RTOSPlugins
            public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context)
            {
                int estimatedStackSize = ProvideEstimatedStackSize(out var pxStack);

                if (_OverflowDetected)
                {
                    return(ReportStackOverflow(estimatedStackSize));
                }

                var rawValue = _BorderVariable?.GetValue() ?? default;

                if (!rawValue.IsValid || CountUnusedStackArea(rawValue.Value) != rawValue.Value.Length)
                {
                    int queriedStackSize;
                    if (_BorderVariable != null)
                    {
                        queriedStackSize = (int)(_BorderVariable.Address - pxStack);
                    }
                    else
                    {
                        queriedStackSize = (int)(_ThreadNode._Engine.ReadMemory(_ThreadNode._Variables.pxTopOfStack).ToUlong() - pxStack);
                    }

                    _BorderVariable?.Dispose();
                    _BorderVariable = null;

                    if (queriedStackSize < 0)
                    {
                        return new LiveWatchNodeState {
                                   Icon = LiveWatchNodeIcon.Error, Value = $"Unexpected stack size ({queriedStackSize})"
                        }
                    }
                    ;

                    var data = _ThreadNode._Engine.Memory.ReadMemory(pxStack, queriedStackSize);
                    if (!data.IsValid)
                    {
                        return new LiveWatchNodeState {
                                   Icon = LiveWatchNodeIcon.Error, Value = $"Failed to read stack contents (0x{pxStack:x8} - 0x{pxStack + (uint)queriedStackSize:x8})"
                        }
                    }
                    ;

                    int offset = CountUnusedStackArea(data.Value);

                    //We don't know whether it is a stack overflow, or if the empty stack is never filled with the pattern.
                    //We assume that if the stack appears overflown from the very beginning, the pattern is not being used at all.
                    _OverflowDetected = offset == 0;
                    if (offset != 0)
                    {
                        _PatternEverFound = true;
                    }

                    if (offset == 0)
                    {
                        return(ReportStackOverflow(estimatedStackSize));
                    }
                    else
                    {
                        int watchSize = Math.Min(_MaxBorderVariableSize, offset);

                        _BorderVariable = _ThreadNode._Engine.Memory.CreateLiveVariable(pxStack + (uint)(offset - watchSize), watchSize, "Stack Border");
                    }
                }

                int freeStack  = (int)(_BorderVariable.Address - pxStack) + _BorderVariable.Size; /* The border variable watches the 1st free slot, not the 1st used one */
                int stackUsage = estimatedStackSize - freeStack;

                RawValue = new LiveVariableValue(rawValue.Timestamp, rawValue.Generation, BitConverter.GetBytes(stackUsage));

                string text;

                if (estimatedStackSize > 0)
                {
                    text = $"{stackUsage}/{estimatedStackSize} bytes";
                }
                else
                {
                    text = $"{stackUsage} bytes";
                }

                return(new LiveWatchNodeState
                {
                    Value = text
                });
            }