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) }; }
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 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); } }
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; }
public KernelNode(NodeSource root, ILiveWatchEngine engine) : base("$rtos.kernel") { _Root = root; _Engine = engine; _xSchedulerRunning = engine.CreateLiveVariable("xSchedulerRunning", false); Name = "Kernel"; Capabilities = LiveWatchCapabilities.CanHaveChildren; }
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; } } }
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"; } }
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; } }
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);