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" } }; } }
public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context) { return(new LiveWatchNodeState { Value = _Root.GetCurrentTaskName(_pxCurrentTCB) }); }
public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context) { return(new LiveWatchNodeState { Value = _LastSeenList.ToString(), Icon = LiveWatchNodeIcon.Thread, }); }
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) }); }
public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context) { RawValue = _StackNode._DistanceToHeapEnd; return(new LiveWatchNodeState { Value = SelectedFormatter.FormatValue(RawValue.Value) }); }
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" }); }
public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context) { var result = new LiveWatchNodeState { Icon = LiveWatchNodeIcon.Thread }; if (context.PreloadChildren) { result.NewChildren = _Root.RefreshThreadList(); } return(result); }
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" }); }
public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context) { var result = new LiveWatchNodeState { Icon = LiveWatchNodeIcon.Queue }; if (context.PreloadChildren) { if (_Children == null) { _Children = _Root.GetAllQueues(); } result.NewChildren = _Children; } return(result); }
public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context) { if (_ThreadList == null) { return(base.UpdateState(context)); } RawValue = _ThreadList.uxNumberOfItems.GetValue(); LiveVariableQueryMode queryMode = LiveVariableQueryMode.UseCacheIfAvailable; ulong[] taskAddresses = null; bool mismatch = true; for (int iter = 0; iter < 3; iter++) { taskAddresses = RunSingleDiscoveryIteration(out var expectedCount, queryMode); if (taskAddresses.Length == expectedCount) { mismatch = false; break; } queryMode = LiveVariableQueryMode.QueryDirectly; } string value = "---"; if (taskAddresses.Length > 0) { value = string.Join(", ", taskAddresses.Select(_Queue._Root.GetThreadName).ToArray()); } if (mismatch) { value += " (imprecise)"; } return(new LiveWatchNodeState { Value = value, Icon = LiveWatchNodeIcon.Thread, }); }
public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context) { var result = new LiveWatchNodeState { Icon = LiveWatchNodeIcon.Graph }; if (_xSchedulerRunning != null) { if (_xSchedulerRunning.GetValue().ToUlong() != 0) { result.Value = "active"; } else { result.Value = "inactive"; } } return(result); }
public virtual LiveWatchNodeState UpdateState(LiveWatchUpdateContext context) => null;
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, }); }
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); }
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 }); }