コード例 #1
0
ファイル: NodeSource.cs プロジェクト: mfkiwl/RTOSPlugins
        public ThreadNode[] RefreshThreadList()
        {
            var foundThreads = new ThreadLookup(this, _AllThreadLists, true, StateThreadListCache).DiscoverAllThreads();
            int generation   = Interlocked.Increment(ref _ThreadListGeneration);

            foreach (var thr in foundThreads)
            {
                if (!_HeapQueried)
                {
                    _HeapQueried = true;
                    _ucHeap      = Engine.Symbols.LookupVariable("ucHeap");
                }

                if (!_CachedThreadNodes.TryGetValue(thr.Key, out var threadObject))
                {
                    string threadName = ReadThreadName(thr.Key, out var pTCB);
                    _CachedThreadNodes[thr.Key] = threadObject = new ThreadNode(Engine, pTCB, threadName, _ucHeap);
                }

                threadObject.UpdateLastSeenState(thr.Value, generation);
            }

            foreach (var kv in _CachedThreadNodes.ToArray())
            {
                kv.Value.MarkMissingIfNeeded(generation);

                if (kv.Value.IsMissingForLongerThan(1000))
                {
                    _CachedThreadNodes.Remove(kv.Key);  //VisualGDB will dispose the node once it realizes it's no longer reported as a child.
                }
            }

            return(_CachedThreadNodes.Values.OrderBy(t => t.Name, StringComparer.InvariantCultureIgnoreCase).ToArray());
        }
コード例 #2
0
ファイル: QueueNodes.cs プロジェクト: mfkiwl/RTOSPlugins
        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);
        }
コード例 #3
0
        public static void Locate(List <ThreadList> result, ILiveWatchEngine engine, IPinnedVariable baseVariable, ThreadListType type, uint listItemOffsetInTCB, bool queryCountVariable = false)
        {
            var list = Locate(engine, baseVariable, type, listItemOffsetInTCB, queryCountVariable);

            if (list != null)
            {
                result.Add(list);
            }
        }
コード例 #4
0
ファイル: ThreadNodes.cs プロジェクト: mfkiwl/RTOSPlugins
        public ThreadNode(ILiveWatchEngine engine, IPinnedVariable pTCB, string threadName, IPinnedVariable ucHeap)
            : base("$rtos.thread." + threadName)
        {
            _Engine = engine;
            _TCB    = pTCB;
            _ucHeap = ucHeap;
            Name    = threadName;

            _Variables.pxTopOfStack     = pTCB.LookupSpecificChild(nameof(_Variables.pxTopOfStack));
            _Variables.pxTopOfStackLive = engine.CreateLiveVariable(_Variables.pxTopOfStack, LiveVariableFlags.CreateSuspended);
            _Variables.uxBasePriority   = pTCB.LookupSpecificChild(nameof(_Variables.uxBasePriority));
            _Variables.uxMutexesHeld    = pTCB.LookupSpecificChild(nameof(_Variables.uxMutexesHeld));
            _Variables.pxStack          = pTCB.LookupSpecificChild(nameof(_Variables.pxStack));

            Capabilities = LiveWatchCapabilities.CanHaveChildren;
        }
コード例 #5
0
        public static ThreadList Locate(ILiveWatchEngine engine, IPinnedVariable baseVariable, ThreadListType type, uint listItemOffsetInTCB, bool queryCountVariable = false)
        {
            if (baseVariable == null)
            {
                return(null);
            }

            var xListEnd = baseVariable?.LookupSpecificChild("xListEnd");

            if (xListEnd == null)
            {
                return(null);
            }

            var xListEnd_pNext = xListEnd.LookupSpecificChild("pxNext");

            if (xListEnd_pNext == null)
            {
                return(null);
            }

            ILiveVariable xListEnd_pNextLive = engine.CreateLiveVariable(xListEnd_pNext);

            if (xListEnd_pNextLive == null)
            {
                return(null);
            }

            ILiveVariable uxNumberOfItemsLive = null;

            if (queryCountVariable)
            {
                var uxNumberOfItems = baseVariable.LookupSpecificChild("uxNumberOfItems");
                if (uxNumberOfItems != null)
                {
                    uxNumberOfItemsLive = engine.CreateLiveVariable(uxNumberOfItems);
                }
            }

            return(new ThreadList(type, xListEnd.Address, xListEnd_pNextLive, baseVariable.UserFriendlyName, uxNumberOfItemsLive, listItemOffsetInTCB));
        }
コード例 #6
0
ファイル: NodeSource.cs プロジェクト: mfkiwl/RTOSPlugins
        string ReadThreadName(ulong TCBAddress, out IPinnedVariable pTCB)
        {
            pTCB = Engine.Symbols.CreateTypedVariable(TCBAddress, _TCBType);

            var    pcTaskName = pTCB.LookupSpecificChild("pcTaskName");
            string threadName = null;

            if (pcTaskName != null)
            {
                try
                {
                    var rawName = Engine.ReadMemory(pcTaskName);
                    threadName = rawName.ToNullTerminatedString();
                }
                catch
                {
                }
            }

            return(threadName ?? $"0x{TCBAddress:x8}");
        }
コード例 #7
0
ファイル: NodeSource.cs プロジェクト: mfkiwl/RTOSPlugins
        public QueueNode[] GetAllQueues()
        {
            List <QueueNode> discoveredQueues = new List <QueueNode>();

            foreach (var globalVar in Engine.Symbols.TopLevelVariables)
            {
                var qt = QueueListNode.ParseQueueType(globalVar.RawType.ToString());

                if (!qt.IsValid)
                {
                    continue;
                }

                IPinnedVariable replacementVariable = null;

                if (qt.ContentsMemberName != null)
                {
                    var child = globalVar.LookupSpecificChild(qt.ContentsMemberName);
                    if (child == null)
                    {
                        continue;
                    }

                    replacementVariable = Engine.Symbols.CreateTypedVariable(child.Address, _QueueType);
                }

                string name = globalVar.UserFriendlyName;
                if (name != null && qt.DiscardedNamePrefix != null && name.StartsWith(qt.DiscardedNamePrefix))
                {
                    name = name.Substring(qt.DiscardedNamePrefix.Length);
                }

                discoveredQueues.Add(new QueueNode(Engine, this, qt, replacementVariable ?? globalVar, _QueueType, name));
            }

            return(discoveredQueues.ToArray());
        }
コード例 #8
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);
        }