Example #1
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 #2
0
 private void ReadLivePoint(tblElement element, LivePoint_DTO livepoint)
 {
     if (element.tblConnector.Gateway_Type == DataGatewayType.Obix.ToString())
     {
         try
         {
             if (_connection_id != element.tblConnector.ID)
             {
                 _connection_id = element.tblConnector.ID;
                 _liveVariable  = new Obix(
                     StringEncryDecry.Decrypt(element.tblConnector.Server_Name, element.tblConnector.SessionID),
                     StringEncryDecry.Decrypt(element.tblConnector.User_Name, element.tblConnector.SessionID),
                     StringEncryDecry.Decrypt(element.tblConnector.Password, element.tblConnector.SessionID));
             }
             LivePoint_ResponseDTO response_dto = new LivePoint_ResponseDTO();
             if (_liveVariable.Is_Connected)
             {
                 response_dto            = _liveVariable.ReadLiveVariable(element.Source_Element_Name_Live);
                 livepoint.Current_Value = response_dto;
             }
             else
             {
                 livepoint.Error_Info = Error_Internal.SetError("Connection Error");
             }
         }
         catch (Exception ex) { }
     }
     else
     {
         throw new Exception("Invalid GatewayType");
     }
 }
Example #3
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 #4
0
            public Node(LinkedListNodeCache linkedListNodeCache, ulong address)
            {
                _Cache   = linkedListNodeCache;
                _Address = address;

                _Variable = _Cache._Engine.Memory.CreateLiveVariable(address + (uint)_Cache._Start, _Cache._Length) ?? throw new Exception($"Failed to create live variable at 0x{address:x8}");
            }
Example #5
0
 public CurrentTaskNode(NodeSource root, ILiveVariable pxCurrentTCB)
     : base("$rtos.kernel.current_task")
 {
     _pxCurrentTCB = pxCurrentTCB;
     _Root         = root;
     Name          = "Current Task";
 }
Example #6
0
 ThreadList(ThreadListType type, ulong endNodeAddress, ILiveVariable xListEnd_pxNext, string name, ILiveVariable uxNumberOfItems, uint listItemOffsetInTCB)
 {
     Type                 = type;
     EndNodeAddress       = endNodeAddress;
     this.xListEnd_pxNext = xListEnd_pxNext;
     this.uxNumberOfItems = uxNumberOfItems;
     _ListItemOffsetInTCB = listItemOffsetInTCB;
     _Name                = name;
 }
Example #7
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 #8
0
            public void Reset()
            {
                uxMessagesWaiting?.Dispose();
                uxMessagesWaiting = null;
                uxLength?.Dispose();
                uxLength = null;

                u_xSemaphore_xMutexHolder?.Dispose();
                u_xSemaphore_xMutexHolder = null;
                u_xSemaphore_uxRecursiveCallCount?.Dispose();
                u_xSemaphore_uxRecursiveCallCount = null;
            }
Example #9
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";
                }
            }
        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 #11
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 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,
            });
        }
Example #13
0
 public string GetCurrentTaskName(ILiveVariable pxCurrentTCB)
 {
     //We use a separate live variable, so that we can suspend it independently. VisualGDB will automatically sort out the redundancies if both variables are enabled.
     return(GetThreadName(pxCurrentTCB.GetValue().ToUlong()));
 }
Example #14
0
            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
                });
            }