Example #1
0
        public NodeSource(ILiveWatchEngine engine)
        {
            Engine = engine;

            _TCBType   = (IPinnedVariableStructType)engine.Symbols.LookupType("TCB_t", true);
            _QueueType = (IPinnedVariableStructType)engine.Symbols.LookupType("Queue_t");

            var xStateListItem_Offset = _TCBType.LookupMember("xStateListItem", true).Offset;

            xEventListItem_Offset = _TCBType.LookupMember("xEventListItem", true).Offset;

            var listItemType   = (IPinnedVariableStructType)engine.Symbols.LookupType("ListItem_t", true);
            var pvOwner_Offset = (int)listItemType.LookupMember("pvOwner", true).Offset;
            var pxNext_Offset  = (int)listItemType.LookupMember("pxNext", true).Offset;

            StateThreadListCache = new LinkedListNodeCache(engine, pvOwner_Offset, pxNext_Offset);
            EventThreadListCache = new LinkedListNodeCache(engine, pvOwner_Offset, pxNext_Offset);

            _pxCurrentTCB           = engine.CreateLiveVariable("pxCurrentTCB", true);
            _uxCurrentNumberOfTasks = engine.CreateLiveVariable("uxCurrentNumberOfTasks", true);

            foreach (var pxReadyTaskList in engine.Symbols.LookupVariable("pxReadyTasksLists")?.LookupChildren(0) ?? new IPinnedVariable[0])
            {
                ThreadList.Locate(_AllThreadLists, engine, pxReadyTaskList, ThreadListType.Ready, xStateListItem_Offset);
            }

            ThreadList.Locate(_AllThreadLists, engine, engine.Symbols.LookupVariable("xDelayedTaskList1"), ThreadListType.Delayed, xStateListItem_Offset);
            ThreadList.Locate(_AllThreadLists, engine, engine.Symbols.LookupVariable("xDelayedTaskList2"), ThreadListType.Delayed, xStateListItem_Offset);
            ThreadList.Locate(_AllThreadLists, engine, engine.Symbols.LookupVariable("xSuspendedTaskList"), ThreadListType.Suspended, xStateListItem_Offset);

            _Children = new ILiveWatchNode[] { new KernelNode(this, engine), new ThreadListNode(this), new QueueListNode(this), new HeapStructureNode(this) };
        }
Example #2
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);
        }
Example #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);
            }
        }
Example #4
0
        public LinkedListNodeCache(ILiveWatchEngine engine, int pvOwner_Offset, int pxNext_Offset)
        {
            _Engine = engine;

            _Start  = Math.Min(pvOwner_Offset, pxNext_Offset);
            _Length = Math.Max(pvOwner_Offset, pxNext_Offset) + 4;

            pvOwner_RelativeOffset = pvOwner_Offset - _Start;
            pxNext_RelativeOffset  = pxNext_Offset - _Start;
        }
Example #5
0
        public KernelNode(NodeSource root, ILiveWatchEngine engine)
            : base("$rtos.kernel")
        {
            _Root              = root;
            _Engine            = engine;
            _xSchedulerRunning = engine.CreateLiveVariable("xSchedulerRunning", false);

            Name         = "Kernel";
            Capabilities = LiveWatchCapabilities.CanHaveChildren;
        }
Example #6
0
        public void Walk(ILiveWatchEngine engine,
                         Dictionary <ulong, ThreadListType> result,
                         HashSet <ulong> processedNodes,
                         int maxThreadsToLoad,
                         LinkedListNodeCache nodeCache,
                         LiveVariableQueryMode queryMode)
        {
            int   threadsFound = 0;
            ulong pxNext       = 0;

            for (var pListNode = xListEnd_pxNext.GetValue(queryMode).ToUlong(); pListNode != 0 && !processedNodes.Contains(pListNode); pListNode = pxNext, threadsFound++)
            {
                if (threadsFound >= maxThreadsToLoad)
                {
                    break;
                }

                processedNodes.Add(pListNode);

                try
                {
                    var pTCB = pListNode - _ListItemOffsetInTCB;

                    var cachedListNode = nodeCache.ProvideNode(pListNode);

                    cachedListNode.ReadValues(queryMode, out ulong pvOwner, out pxNext);

                    if (pvOwner != pTCB)
                    {
                        if ((uint)pvOwner == uint.MaxValue)
                        {
                            //This is the end-of-list node. Continue checking past it.
                            continue;
                        }
                        else
                        {
                            //The list node doesn't point to the object itself anymore. Most likely, it has been freed and reused.
                            cachedListNode.RemoveFromCache();
                            break;
                        }
                    }

                    result[pTCB] = Type;
                }
                catch (Exception ex)
                {
                    engine.LogException(ex, $"failed to process TCB node at {pListNode}");
                    break;
                }
            }
        }
Example #7
0
            public HeapUsageNode(ILiveWatchEngine engine, ILiveVariable variable, HeapNodeType type, int heapSize)
                : base("$rtos.kernel.heap_current")
            {
                _Variable         = variable;
                _HeapSize         = heapSize;
                SelectedFormatter = engine.GetDefaultFormatter(ScalarVariableType.SInt32);

                if (type == HeapNodeType.Current)
                {
                    Name = "Heap Usage";
                }
                else
                {
                    Name = "Max. Heap Usage";
                }
            }
Example #8
0
        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;
        }
        public StackInfoNode(ILiveWatchEngine engine)
            : base("$stack")
        {
            _Engine                = engine;
            SelectedFormatter      = engine.GetDefaultFormatter(ScalarVariableType.SInt32);
            _UnusedStackFillPatern = engine.Settings.UnusedStackFillPattern;
            _MaxBorderVariableSize = engine.Settings.StackBorderWatchSize;

            Name          = "Highest Stack Usage";
            Capabilities |= LiveWatchCapabilities.CanHaveChildren;

            try
            {
                var endOfStackVariable = engine.Symbols.TryLookupRawSymbolInfo("_estack") ?? engine.Symbols.TryLookupRawSymbolInfo("__StackLimit") ?? throw new Exception("No '_estack' or '__StackLimit' symbol found.");
                _StackEnd = endOfStackVariable.Address;

                var reservedForStackVariable = engine.Symbols.LookupVariable("ReservedForStack");
                if (reservedForStackVariable != null && reservedForStackVariable.Size != 0)
                {
                    //Stack size is fixed. No need to monitor outside it.
                    _StackStart = _StackEnd - (uint)reservedForStackVariable.Size;
                }
                else
                {
                    //Stack size is variable. Initially, it starts right after the 'end' symbol, but can be moved further as the heap grows.
                    var endVariable = engine.Symbols.TryLookupRawSymbolInfo("end") ??
                                      engine.Symbols.TryLookupRawSymbolInfo("_ebss") ??
                                      engine.Symbols.TryLookupRawSymbolInfo("_edata") ?? throw new Exception("Could not find 'end', '_ebss' or '_edata'");
                    var heapEndVariableAddress = engine.Symbols.FindSymbolsContainingString("heap_end").SingleOrDefault().Address;
                    if (heapEndVariableAddress != 0)
                    {
                        _HeapEndVariable = engine.Memory.CreateLiveVariable(heapEndVariableAddress, 4);
                    }

                    _StackStart = endVariable.Address;
                    _StackOpposesGrowingHeap = true;
                }
            }
            catch (Exception ex)
            {
                _Error = ex.Message;
            }
        }
Example #10
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));
        }
 public NodeSource(ILiveWatchEngine engine)
 {
     _Engine = engine;
 }
 public ILiveWatchNodeSource CreateNodeSource(ILiveWatchEngine engine) => new NodeSource(engine);