Пример #1
0
        internal override IList <ClrStackFrame> GetExceptionStackTrace(ulong obj, ClrType type)
        {
            List <ClrStackFrame> result = new List <ClrStackFrame>();

            if (!GetStackTraceFromField(type, obj, out ulong _stackTrace))
            {
                if (!ReadPointer(obj + GetStackTraceOffset(), out _stackTrace))
                {
                    return(result);
                }
            }

            if (_stackTrace == 0)
            {
                return(result);
            }

            DesktopGCHeap heap           = (DesktopGCHeap)Heap;
            ClrType       stackTraceType = heap.GetObjectType(_stackTrace);

            if (stackTraceType == null)
            {
                stackTraceType = heap.ArrayType;
            }

            if (!stackTraceType.IsArray)
            {
                return(result);
            }

            int len = stackTraceType.GetArrayLength(_stackTrace);

            if (len == 0)
            {
                return(result);
            }

            int   elementSize = CLRVersion == DesktopVersion.v2 ? IntPtr.Size * 4 : IntPtr.Size * 3;
            ulong dataPtr     = _stackTrace + (ulong)(IntPtr.Size * 2);

            if (!ReadPointer(dataPtr, out ulong count))
            {
                return(result);
            }

            // Skip size and header
            dataPtr += (ulong)(IntPtr.Size * 2);

            DesktopThread thread = null;

            for (int i = 0; i < (int)count; ++i)
            {
                if (!ReadPointer(dataPtr, out ulong ip))
                {
                    break;
                }
                if (!ReadPointer(dataPtr + (ulong)IntPtr.Size, out ulong sp))
                {
                    break;
                }
                if (!ReadPointer(dataPtr + (ulong)(2 * IntPtr.Size), out ulong md))
                {
                    break;
                }

                if (i == 0)
                {
                    thread = (DesktopThread)GetThreadByStackAddress(sp);
                }

                result.Add(new DesktopStackFrame(this, thread, null, ip, sp, md));

                dataPtr += (ulong)elementSize;
            }

            return(result);
        }
Пример #2
0
        internal DesktopBlockingObject[] InitLockInspection()
        {
            if (_result != null)
            {
                return(_result);
            }

            // First, enumerate all thinlocks on the heap.
            foreach (var seg in _heap.Segments)
            {
                for (ulong obj = seg.FirstObject; obj != 0; obj = seg.NextObject(obj))
                {
                    ClrType type = _heap.GetObjectType(obj);
                    if (IsReaderWriterLock(obj, type))
                    {
                        _locks[obj] = CreateRWLObject(obj, type);
                    }
                    else if (IsReaderWriterSlim(obj, type))
                    {
                        _locks[obj] = CreateRWSObject(obj, type);
                    }

                    // Does this object have a syncblk with monitor associated with it?
                    if (!_heap.GetObjectHeader(obj, out uint header))
                    {
                        continue;
                    }

                    if ((header & (BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX | BIT_SBLK_SPIN_LOCK)) != 0)
                    {
                        continue;
                    }

                    uint threadId = header & SBLK_MASK_LOCK_THREADID;
                    if (threadId == 0)
                    {
                        continue;
                    }

                    ClrThread thread = _runtime.GetThreadFromThinlockID(threadId);
                    if (thread != null)
                    {
                        int recursion = ((int)header & SBLK_MASK_LOCK_RECLEVEL) >> SBLK_RECLEVEL_SHIFT;
                        _monitors[obj] = new DesktopBlockingObject(obj, true, recursion + 1, thread, BlockingReason.Monitor);
                    }
                }
            }

            // Enumerate syncblocks to find locks
            int syncblkCnt = _runtime.GetSyncblkCount();

            for (int i = 0; i < syncblkCnt; ++i)
            {
                ISyncBlkData data = _runtime.GetSyncblkData(i);
                if (data == null || data.Free)
                {
                    continue;
                }

                _syncblks[data.Address] = data.Object;
                _syncblks[data.Object]  = data.Object;
                ClrThread thread = null;
                if (data.MonitorHeld)
                {
                    ulong threadAddr = data.OwningThread;
                    foreach (var clrThread in _runtime.Threads)
                    {
                        if (clrThread.Address == threadAddr)
                        {
                            thread = clrThread;
                            break;
                        }
                    }
                }

                _monitors[data.Object] = new DesktopBlockingObject(data.Object, data.MonitorHeld, (int)data.Recursion, thread, BlockingReason.Monitor);
            }

            SetThreadWaiters();

            int total = _monitors.Count + _locks.Count + _joinLocks.Count + _waitLocks.Count;

            _result = new DesktopBlockingObject[total];

            int j = 0;

            foreach (DesktopBlockingObject blocker in _monitors.Values)
            {
                _result[j++] = blocker;
            }

            foreach (DesktopBlockingObject blocker in _locks.Values)
            {
                _result[j++] = blocker;
            }

            foreach (DesktopBlockingObject blocker in _joinLocks.Values)
            {
                _result[j++] = blocker;
            }

            foreach (DesktopBlockingObject blocker in _waitLocks.Values)
            {
                _result[j++] = blocker;
            }

            Debug.Assert(j == _result.Length);

            // Free up some memory.
            _monitors  = null;
            _locks     = null;
            _joinLocks = null;
            _waitLocks = null;
            _syncblks  = null;

            return(_result);
        }