private MemoryAnalyzer(DataTarget dataTarget)
        {
            // TODO: Exit gracefully for memory dumps from different platforms

            m_dataTarget = dataTarget;
            string dacLocation = m_dataTarget.ClrVersions[0].TryGetDacLocation();
            if (String.IsNullOrEmpty(dacLocation))
                throw new ArgumentException("Cannot find DAC location for process");

            m_runtime = m_dataTarget.CreateRuntime(dacLocation);
            m_heap = m_runtime.GetHeap();
        }
Example #2
0
        public void Execute(CommandExecutionContext context)
        {
            _context = context;

            if (!CommandHelpers.VerifyValidObjectAddress(context, ObjectAddress))
                return;

            _heap = context.Heap;
            if (!_heap.CanWalkHeap)
            {
                context.WriteErrorLine("The heap is not in a walkable state.");
                return;
            }

            var type = _heap.GetObjectType(ObjectAddress);

            _visitedObjects = new ObjectSet(_heap);
            _targets[ObjectAddress] = new Node(ObjectAddress, type);
            FillRootDictionary();

            foreach (var root in _roots)
            {
                if (_visitedRoots.Contains(root) || _visitedObjects.Contains(root.Object))
                    continue;

                Node path = TryFindPathToTarget(root);
                if (path != null)
                    PrintOnePath(path);
            }
        }
Example #3
0
        public ObjectSet(ClrHeap heap)
        {
            _shift = IntPtr.Size == 4 ? 3 : 4;
            int count = heap.Segments.Count;

            _data = new BitArray[count];
            _entries = new Entry[count];
            #if DEBUG
            ulong last = 0;
            #endif

            for (int i = 0; i < count; ++i)
            {
                var seg = heap.Segments[i];
            #if DEBUG
                Debug.Assert(last < seg.Start);
                last = seg.Start;
            #endif

                _data[i] = new BitArray(GetBitOffset(seg.Length));
                _entries[i].Low = seg.Start;
                _entries[i].High = seg.End;
                _entries[i].Index = i;
            }
        }
Example #4
0
        // Returns all objects being kept alive by the input object
        // Based off the code at https://github.com/Microsoft/clrmd/blob/master/Documentation/WalkingTheHeap.md
        public static List<ulong> GetReferencedObjects(ClrHeap heap, ulong obj)
        {
            List<ulong> references = new List<ulong>();
            Stack<ulong> eval = new Stack<ulong>();

            HashSet<ulong> considered = new HashSet<ulong>();

            eval.Push(obj);

            while (eval.Count > 0)
            {
                obj = eval.Pop();
                if (considered.Contains(obj))
                    continue;

                considered.Add(obj);

                // Grab the type. We will only get null here in the case of heap corruption.
                ClrType type = heap.GetObjectType(obj);
                if (type == null)
                    continue;

                references.Add(obj);

                // Now enumerate all objects that this object points to, add them to the
                // evaluation stack if we haven't seen them before.
                type.EnumerateRefsOfObjectCarefully(obj, delegate (ulong child, int offset)
                {
                    if (child != 0 && !considered.Contains(child))
                        eval.Push(child);
                });
            }

            return references;
        }
Example #5
0
        private static IEnumerable<Tuple<ulong, ClrType>> EnumerateFromObjectSet(ClrHeap heap, IEnumerable<ulong> objects)
        {
            var toGoThrough = new Stack<ulong>(objects);
            var seen = new ObjectSet(heap);

            while (toGoThrough.Count > 0)
            {
                var obj = toGoThrough.Pop();
                if (seen.Contains(obj))
                    continue;

                seen.Add(obj);

                var type = heap.GetObjectType(obj);
                if (type == null || type.IsFree || String.IsNullOrEmpty(type.Name))
                    continue;

                yield return new Tuple<ulong, ClrType>(obj, type);

                type.EnumerateRefsOfObject(obj, (child, _) =>
                {
                    if (child != 0 && !seen.Contains(child))
                    {
                        toGoThrough.Push(child);
                    }
                });
            }
        }
Example #6
0
 public ClrNullValue(ClrHeap heap)
 {
     foreach (var type in heap.EnumerateTypes())
     {
         s_free = type;
         break;
     }
 }
Example #7
0
        /// <summary>
        ///     Converts the specified heap.
        /// </summary>
        /// <param name="heap">The heap.</param>
        /// <returns>IClrHeap.</returns>
        public IClrHeap Convert(ClrMd.ClrHeap heap)
        {
            if (heap == null)
            {
                return(null);
            }
            var item = new HeapAdapter(this, heap);

            return(Cache.GetOrAdd <IClrHeap>(heap, () => item, () => item.Setup()));
        }
        public ClrDynamicClass(ClrHeap heap, ClrType type)
        {
            if (heap == null)
                throw new ArgumentNullException("heap");

            if (type == null)
                throw new ArgumentNullException("type");

            m_heap = heap;
            m_type = type;
        }
Example #9
0
        public ClrObject(ClrHeap heap, ClrType type, ulong addr, bool inner)
        {
            if (heap == null)
                throw new ArgumentNullException("heap");

            m_addr = addr;
            m_inner = inner;
            m_heap = heap;

            // For interior pointers (structs inside other objects), we simply have to trust the caller
            // gave us the right thing.
            m_type = inner ? type : heap.GetObjectType(addr);
        }
		public ClrHeapDecorator(ClrRuntime clrRuntime, ThreadDispatcher threadDispatcher)
		{
			_threadDispatcher = threadDispatcher;
			_clrHeap = threadDispatcher.Process(() => clrRuntime.GetHeap());

			

			_threadDispatcher.Process(()=>
			{
				objectIndex = IndexBuilder.Build(_clrHeap);
				GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
			});
		}
			public static MultiElementDictionary2<ulong> Build(ClrHeap heap)
			{

				var result = new MultiElementDictionary2<ulong>();

				foreach (var objRef in heap.EnumerateObjects())
				{
					var type = heap.GetObjectType(objRef);
					result.Add(type.Name, objRef);
				}

				return result;
			}
Example #12
0
    static object Format(ClrHeap heap, object val)
    {
        if (val == null)
            return "{null}";

        if (val is ulong)
        {
            ulong addr = (ulong)val;
            var type = heap.GetObjectType(addr);
            if (type != null && type.Name == "System.String")
                return type.GetValue(addr);
            else
                return ((ulong)val).ToString("X");
        }

        return val;
    }
Example #13
0
        public ClrObject(ClrHeap heap, ClrType type, ulong addr)
        {
            if (heap == null)
                throw new ArgumentNullException("heap");

            m_addr = addr;
            m_heap = heap;

            if (addr != 0)
            {
                var gcType = heap.GetObjectType(addr);
                if (gcType != null)
                    type = gcType;
            }

            m_type = type;
        }
Example #14
0
        internal virtual IEnumerable <ClrRoot> EnumerateStackReferences(ClrThread thread, bool includeDead)
        {
            Address stackBase  = thread.StackBase;
            Address stackLimit = thread.StackLimit;

            if (stackLimit <= stackBase)
            {
                Address tmp = stackLimit;
                stackLimit = stackBase;
                stackBase  = tmp;
            }

            ClrAppDomain domain = GetAppDomainByAddress(thread.AppDomain);
            ClrHeap      heap   = GetHeap();
            var          mask   = ((ulong)(PointerSize - 1));
            var          cache  = MemoryReader;

            cache.EnsureRangeInCache(stackBase);
            for (Address stackPtr = stackBase; stackPtr < stackLimit; stackPtr += (uint)PointerSize)
            {
                Address objRef;
                if (cache.ReadPtr(stackPtr, out objRef))
                {
                    // If the value isn't pointer aligned, it cannot be a managed pointer.
                    if (heap.IsInHeap(objRef))
                    {
                        ulong mt;
                        if (heap.ReadPointer(objRef, out mt))
                        {
                            ClrType type = null;

                            if (mt > 1024)
                            {
                                type = heap.GetObjectType(objRef);
                            }

                            if (type != null && !type.IsFree)
                            {
                                yield return(new LocalVarRoot(stackPtr, objRef, type, domain, thread, false, true, false));
                            }
                        }
                    }
                }
            }
        }
Example #15
0
        /// <summary>
        /// Returns a ClrObject for this value.
        /// </summary>
        /// <returns>A ClrObject for this value.  If the value is null, then ClrObject.IsNull will the true and ClrObject.Type
        /// will equal ClrHeap.ErrorType.</returns>
        public virtual ClrObject AsObject()
        {
            if (!ClrRuntime.IsObjectReference(ElementType))
            {
                throw new InvalidOperationException("Value is not an object.");
            }

            if (IsNull)
            {
                throw new NullReferenceException();
            }

            ClrHeap heap = Runtime.GetHeap();

            ulong obj = Object;

            return(new ClrObject(obj, obj != 0 ? heap.GetObjectType(obj) : heap.NullType));
        }
Example #16
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="heap">A ClrHeap to add objects from.</param>
        public ObjectSet(ClrHeap heap)
        {
            _heap       = heap;
            _minObjSize = heap.PointerSize * 3;

            _segments = new HeapHashSegment[_heap.Segments.Count];

            for (int i = 0; i < _segments.Length; i++)
            {
                ulong start = _heap.Segments[i].Start;
                ulong end   = _heap.Segments[i].End;
                _segments[i] = new HeapHashSegment
                {
                    StartAddress = start,
                    EndAddress   = end,
                    Objects      = new BitArray(checked ((int)(end - start) / _minObjSize), false)
                };
            }
        }
Example #17
0
        /// <summary>
        /// Gets the given object reference field from this ClrObject.
        /// </summary>
        /// <param name="fieldName">The name of the field to retrieve.</param>
        /// <returns>A ClrObject of the given field.</returns>
        /// <exception cref="ArgumentException">
        /// The given field does not exist in the object.
        /// -or-
        /// The given field was not an object reference.
        /// </exception>
        public ClrObject GetObjectField(string fieldName)
        {
            ClrInstanceField?field = Type.GetFieldByName(fieldName);

            if (field is null)
            {
                throw new ArgumentException($"Type '{Type.Name}' does not contain a field named '{fieldName}'");
            }

            if (!field.IsObjectReference)
            {
                throw new ArgumentException($"Field '{Type.Name}.{fieldName}' is not an object reference.");
            }

            ClrHeap heap = Type.Heap;

            ulong addr = field.GetAddress(Address, _interior);

            if (!DataReader.ReadPointer(addr, out ulong obj))
            {
                return(default);
        private void GetObjSize(ClrHeap heap, ulong obj, out uint count, out ulong size)
        {
            // Evaluation stack
            var eval = new Stack<ulong>();

            // To make sure we don't count the same object twice, we'll keep a set of all objects
            // we've seen before.
            var considered = new HashSet<ulong>();

            count = 0;
            size = 0;
            eval.Push(obj);

            while (eval.Count > 0)
            {
                // Pop an object, ignore it if we've seen it before.
                obj = eval.Pop();
                if (!considered.Add(obj))
                    continue;

                // Grab the type. We will only get null here in the case of heap corruption.
                ClrType type = heap.GetObjectType(obj);
                if (type == null)
                    continue;

                count++;
                size += type.GetSize(obj);

                // Now enumerate all objects that this object points to, add them to the
                // evaluation stack if we haven't seen them before.
                type.EnumerateRefsOfObject(obj, (child, offset) =>
                {
                    if (child != 0 && !considered.Contains(child))
                        eval.Push(child);
                });
            }
        }
Example #19
0
        internal static bool GetStaticField(ClrHeap heap, ClrType type, GetMemberBinder binder, out object result)
        {
            result = null;
            bool success = false;
            ClrStaticField field = null;

            StringComparison compare = binder.IgnoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture;
            foreach (var inst in type.StaticFields)
            {
                if (inst.Name.Equals(binder.Name, compare))
                {
                    field = inst;
                    break;
                }
            }

            if (field != null)
            {
                result = new StaticVariableValueWrapper(heap, field);
                success = true;
            }

            return success;
        }
Example #20
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="heap">A ClrHeap to add objects from.</param>
        public ObjectSet(ClrHeap heap)
        {
            Heap = heap ?? throw new ArgumentNullException(nameof(heap));

            List <HeapHashSegment> segments = new List <HeapHashSegment>(heap.Segments.Length);

            foreach (ClrSegment seg in heap.Segments)
            {
                ulong start = seg.Start;
                ulong end   = seg.End;

                if (start < end)
                {
                    segments.Add(new HeapHashSegment
                    {
                        StartAddress = start,
                        EndAddress   = end,
                        Objects      = new BitArray((int)(end - start) / MinObjSize, false)
                    });
                }
            }

            _segments = segments.ToArray();
        }
 public async Task<IEnumerable<object>> Execute(Models.OperationModel model, CancellationToken token, object customeParameter)
 {
     return await DebuggerSession.Instance.ExecuteOperation(() =>
     {
         _token = token;
         _heap = DebuggerSession.Instance.Runtime.GetHeap();
         _found = false;
         var stack = new Stack<ulong>();
         foreach (var root in _heap.EnumerateRoots())
         {
             stack.Clear();
             stack.Push(root.Object);
             if (token.IsCancellationRequested)
                 break;
             GetRefChainFromRootToObject(model.ObjectAddress, stack, new HashSet<ulong>());
             if (_found) break;
         }
         var enumerable = from address in stack
                          orderby address ascending
                          let type = _heap.GetObjectType(address)
                          select new { Address = address, Type = type.Name, MetadataToken = type.MetadataToken, };
         return enumerable.ToList();
     });
 }
Example #22
0
        private static void PrintDiagnosticInfo(DataTarget dt, ClrRuntime runtime, ClrHeap heap)
        {
            Console.WriteLine("DataTarget Info:");
            Console.WriteLine("  ClrVersions: " + String.Join(", ", dt.ClrVersions));
            Console.WriteLine("  IsMinidump: " + dt.IsMinidump);
            Console.WriteLine("  Architecture: " + dt.Architecture);
            Console.WriteLine("  PointerSize: " + dt.PointerSize);
            Console.WriteLine("  SymbolPath: " + dt.GetSymbolPath());

            Console.WriteLine("ClrRuntime Info:");
            Console.WriteLine("  ServerGC: " + runtime.ServerGC);
            Console.WriteLine("  HeapCount: " + runtime.HeapCount);
            Console.WriteLine("  Thread Count: " + runtime.Threads.Count);

            Console.WriteLine("ClrRuntime Modules:");
            foreach (var module in runtime.EnumerateModules())
            {
                Console.WriteLine("  {0,26} Id:{1}, {2,10:N0} bytes @ 0x{3:X8}",
                                  Path.GetFileName(module.FileName), module.AssemblyId, module.Size, module.ImageBase);
            }

            Console.WriteLine("ClrHeap Info:");
            Console.WriteLine("  TotalHeapSize: " + heap.TotalHeapSize);
            Console.WriteLine("  Segments: " + heap.Segments.Count);
            Console.WriteLine("  Gen0 Size: " + heap.GetSizeByGen(0));
            Console.WriteLine("  Gen1 Size: " + heap.GetSizeByGen(1));
            Console.WriteLine("  Gen2 Size: " + heap.GetSizeByGen(2));
            Console.WriteLine("  Gen3 Size: " + heap.GetSizeByGen(3));
        }
 public StaticVariableValueWrapper(ClrHeap heap, ClrStaticField field)
 {
     m_heap = heap;
     m_field = field;
 }
Example #24
0
 /// <summary>
 /// Creates a GCRoot helper object for the given heap.
 /// </summary>
 /// <param name="heap">The heap the object in question is on.</param>
 public GCRoot(ClrHeap heap)
 {
     _heap     = heap ?? throw new ArgumentNullException(nameof(heap));
     _maxTasks = Environment.ProcessorCount * 2;
 }
Example #25
0
        private static Node FindPathToTarget(ClrHeap heap, ClrRoot root)
        {
            ClrType type = heap.GetObjectType(root.Object);
            if (type == null)
                return null;

            List<ulong> refList = new List<ulong>();
            List<int> offsetList = new List<int>();

            Node curr = new Node(root.Object, type);
            while (curr != null)
            {
                if (curr.Children == null)
                {
                    refList.Clear();
                    offsetList.Clear();

                    curr.Type.EnumerateRefsOfObject(curr.Object, delegate(ulong child, int offset)
                    {
                        if (child != 0)
                        {
                            refList.Add(child);
                            offsetList.Add(offset);
                        }
                    });

                    curr.Children = refList.ToArray();
                    curr.Offsets = offsetList.ToArray();
                }
                else
                {
                    if (curr.Curr < curr.Children.Length)
                    {
                        ulong nextObj = curr.Children[curr.Curr];
                        int offset = curr.Offsets[curr.Curr];
                        curr.Curr++;

                        if (m_considered.Contains(nextObj))
                            continue;

                        m_considered.Add(nextObj);

                        Node next = null;
                        if (m_targets.TryGetValue(nextObj, out next))
                        {
                            curr.Next = next;
                            next.Prev = curr;
                            next.Offset = offset;

                            while (curr.Prev != null)
                            {
                                m_targets[curr.Object] = curr;
                                curr = curr.Prev;
                            }

                            m_targets[curr.Object] = curr;
                            return curr;
                        }

                        type = heap.GetObjectType(nextObj);
                        if (type != null && type.ContainsPointers)
                        {
                            curr = new Node(nextObj, type, curr);
                            curr.Offset = offset;
                        }
                    }
                    else
                    {
                        curr = curr.Prev;

                        if (curr != null)
                            curr.Next = null;
                    }
                }
            }

            return null;
        }
Example #26
0
 public static IEnumerable <dynamic> GetProxies <T>(this ClrHeap heap)
 {
     return(GetProxies(heap, typeof(T).FullName));
 }
Example #27
0
 public ParallelObjectSet(ClrHeap heap) : base(heap)
 {
 }
Example #28
0
        public static KcpUserAccount GetKcpUserAccountInfo(ulong KcpUserAccountAddr, ClrType KcpUserAccountType, ClrHeap Heap, string databaseLocation)
        {
            KcpUserAccount UserAccountInfo = new KcpUserAccount();

            // Get the embedded ProtectedBinary
            ClrInstanceField KcpProtectedBinaryField = KcpUserAccountType.GetFieldByName("m_pbKeyData");
            ulong KcpProtectedBinaryAddr = KcpProtectedBinaryField.GetAddress(KcpUserAccountAddr);
            ulong KcpProtectedBinaryObjAddr = (ulong)KcpProtectedBinaryField.GetValue(KcpUserAccountAddr);

            ClrInstanceField EncDataField = KcpProtectedBinaryField.Type.GetFieldByName("m_pbData");
            ulong EncDataAddr = EncDataField.GetAddress(KcpProtectedBinaryObjAddr);
            ulong EncDataArrayAddr = (ulong)EncDataField.GetValue(KcpProtectedBinaryObjAddr);

            ClrType EncDataArrayType = Heap.GetObjectType(EncDataArrayAddr);
            int len = EncDataField.Type.GetArrayLength(EncDataArrayAddr);

            if (len <= 0 || len % 16 != 0) // Small sanity check to make sure everything's ok
                return null;

            byte[] EncData = new byte[len];
            for (int i = 0; i < len; i++)
            {
                EncData[i] = (byte)EncDataArrayType.GetArrayElementValue(EncDataArrayAddr, i);
            }

            UserAccountInfo.databaseLocation = databaseLocation;
            UserAccountInfo.encryptedBlob = EncData;
            UserAccountInfo.encryptedBlobAddress = (IntPtr)KcpUserAccountType.GetArrayElementAddress(EncDataArrayAddr, 0);
            UserAccountInfo.encryptedBlobLen = len;

            return UserAccountInfo;
        }
Example #29
0
        public void Execute(CommandExecutionContext context)
        {
            if (!String.IsNullOrEmpty(TypeRegex))
            {
                try
                {
                    new Regex(TypeRegex);
                }
                catch (ArgumentException)
                {
                    context.WriteErrorLine("The regular expression specified for --type is not valid; did you forget to escape regex characters?");
                    return;
                }
            }

            _heap = context.Runtime.GetHeap();
            if (!_heap.CanWalkHeap)
            {
                context.WriteErrorLine("The heap is not in a walkable state.");
                return;
            }

            var typeInfos = new Dictionary<ulong, TypeInfo>(); // MT to TypeInfo
            long totalObjectCount = 0;
            if (!StatisticsOnly)
            {
                context.WriteLine("{0,-20} {1,-20} {2}", "MT", "Address", "Size");
            }
            foreach (var obj in _heap.EnumerateObjectAddresses())
            {
                ulong mt = 0;
                context.Runtime.ReadPointer(obj, out mt);

                if (!FilterObject(obj, mt))
                    continue;

                var type = _heap.GetObjectType(obj);
                if (type == null || String.IsNullOrEmpty(type.Name))
                    continue;

                var size = type.GetSize(obj);

                if (!StatisticsOnly)
                {
                    context.WriteLine("{0,-20:x16} {1,-20:x16} {2,-10}", mt, obj, size);
                }
                if (typeInfos.ContainsKey(mt))
                {
                    var current = typeInfos[mt];
                    current.Count += 1;
                    current.Size += size;
                    typeInfos[mt] = current;
                }
                else
                {
                    var objType = _heap.GetObjectType(obj);
                    var objTypeName = objType != null ? objType.Name : "<no name>";
                    typeInfos.Add(mt, new TypeInfo { Size = size, Count = 1, TypeName = objTypeName });
                }
                ++totalObjectCount;
            }

            context.WriteLine("Statistics:");
            context.WriteLine("{0,-20} {1,-10} {2,-10} {3}", "MT", "Count", "TotalSize", "Class Name");
            foreach (var kvp in (from e in typeInfos orderby e.Value.Size ascending select e))
            {
                context.WriteLine("{0,-20:x16} {1,-10} {2,-10} {3}",
                    kvp.Key, kvp.Value.Count, kvp.Value.Size, kvp.Value.TypeName);
            }
            context.WriteLine("Total {0} objects", totalObjectCount);
        }
Example #30
0
        internal ClrHandle(Microsoft.Diagnostics.Runtime.Desktop.V45Runtime clr, ClrHeap heap, Microsoft.Diagnostics.Runtime.Desktop.HandleData handleData)
        {
            Address obj;
            Address = handleData.Handle;
            clr.ReadPointer(Address, out obj);

            Object = obj;
            Type = heap.GetObjectType(obj);

            uint refCount = 0;

            if (handleData.Type == (int)HandleType.RefCount)
            {
                if (handleData.IsPegged != 0)
                    refCount = handleData.JupiterRefCount;

                if (refCount < handleData.RefCount)
                    refCount = handleData.RefCount;

                if (Type != null)
                {
                    if (Type.IsCCW(obj))
                    {
                        CcwData data = Type.GetCCWData(obj);
                        if (data != null && refCount < data.RefCount)
                            refCount = (uint)data.RefCount;
                    }
                    else if (Type.IsRCW(obj))
                    {
                        RcwData data = Type.GetRCWData(obj);
                        if (data != null && refCount < data.RefCount)
                            refCount = (uint)data.RefCount;
                    }
                }

                RefCount = refCount;
            }


            HandleType = (HandleType)handleData.Type;
            AppDomain = clr.GetAppDomainByAddress(handleData.AppDomain);

            if (HandleType == HandleType.Dependent)
            {
                DependentTarget = handleData.Secondary;
                DependentType = heap.GetObjectType(handleData.Secondary);
            }
        }
Example #31
0
 public ClrValueImpl(ClrHeap heap)
     : base(heap.Runtime)
 {
     _address = 0;
     _type    = heap.NullType;
 }
Example #32
0
 private void CreateRuntime(int clrVersionIndex, string dacLocation)
 {
     _runtime = _target.ClrVersions[clrVersionIndex].CreateRuntime(dacLocation);
     _heap = _runtime.GetHeap();
 }
Example #33
0
 /// <summary>
 /// Creates a GCRoot helper object for the given heap.
 /// </summary>
 /// <param name="heap">The heap the object in question is on.</param>
 public GCRoot(ClrHeap heap)
 {
     Heap = heap ?? throw new ArgumentNullException(nameof(heap));
 }
Example #34
0
        private static ObjectSet GetLiveObjects(ClrHeap heap)
        {
            ObjectSet considered = new ObjectSet(heap);
            Stack<ulong> eval = new Stack<ulong>();

            foreach (var root in heap.EnumerateRoots())
                eval.Push(root.Object);

            while (eval.Count > 0)
            {
                ulong obj = eval.Pop();
                if (considered.Contains(obj))
                    continue;

                considered.Add(obj);

                var type = heap.GetObjectType(obj);
                if (type == null)  // Only if heap corruption
                    continue;

                type.EnumerateRefsOfObject(obj, delegate(ulong child, int offset)
                {
                    if (child != 0 && !considered.Contains(child))
                        eval.Push(child);
                });
            }

            return considered;
        }
Example #35
0
        private static byte[] ReadBuffer(ClrHeap heap, ulong address, int length)
        {
            byte[] buffer = new byte[length];
            int byteRead = heap.ReadMemory(address, buffer, 0, buffer.Length);

            if (byteRead != length)
                throw new InvalidOperationException(string.Format("Expected to read {0} bytes and actually read {1}", length, byteRead));

            return buffer;
        }
Example #36
0
        private static void PrintGCHeapInfo(ClrRuntime runtime, ClrHeap heap)
        {
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            Console.WriteLine("\nGC Heap Information - {0}", runtime.ServerGC ? "Server" : "Workstation");
            Console.ResetColor();

            var seperator = "-----------------------------------------------------------";
            var heapSegmentInfo = from seg in heap.Segments
                               group seg by seg.ProcessorAffinity into g
                               orderby g.Key
                               select new
                               {
                                   Heap = g.Key,
                                   Size = g.Sum(p => (uint)p.Length)
                               };
            foreach (var item in heapSegmentInfo)
            {
                Console.WriteLine(seperator);
                Console.ForegroundColor = ConsoleColor.DarkGreen;
                Console.WriteLine("Heap {0,2}: {1,12:N0} bytes ({2:N2} MB) in use", 
                                  item.Heap, item.Size, item.Size / 1024.0 / 1024.0);
                Console.ResetColor();
                Console.WriteLine(seperator);
                Console.WriteLine("{0,12} {1,12} {2,14} {3,14}", "Type", "Size (MB)", "Committed (MB)", "Reserved (MB)");
                Console.WriteLine(seperator);
                var heapSegments = heap.Segments.Where(s => s.ProcessorAffinity == item.Heap)
                                                .OrderBy(s => s.IsEphemeral ? 1 : 0 + (s.IsLarge ? 3 : 2));
                foreach (ClrSegment segment in heapSegments)
                {
                    string type;
                    if (segment.IsEphemeral)
                        type = "Ephemeral";
                    else if (segment.IsLarge)
                        type = "Large";
                    else
                        type = "Gen2";

                    Console.WriteLine("{0,12} {1,12:N2} {2,14:N2} {3,14:N2}", 
                                      type,                                
                                      (segment.End - segment.Start) / 1024.0 / 1024.0, // This is the same as segment.Length
                                      (segment.CommittedEnd - segment.Start) / 1024.0 / 1024.0,
                                      (segment.ReservedEnd - segment.Start) / 1024.0 / 1024.0);
                }
            }
            Console.WriteLine(seperator);
            Console.WriteLine("Total (across all heaps): {0:N0} bytes ({1:N2} MB)", 
                              heap.Segments.Sum(s => (long)s.Length), 
                              heap.Segments.Sum(s => (long)s.Length) / 1024.0 / 1024.0);
            Console.WriteLine(seperator);
        }
Example #37
0
 internal UnknownType(ClrHeap heap)
 {
     m_heap = heap;
 }
Example #38
0
        private static void ExamineProcessHeap(ClrRuntime runtime, ClrHeap heap, bool showGcHeapInfo)
        {            
            if (!heap.CanWalkHeap)
            {
                Console.WriteLine("Cannot walk the heap!");
                return;
            }

            ulong totalStringObjectSize = 0, stringObjectCounter = 0, byteArraySize = 0;
            ulong asciiStringSize = 0, unicodeStringSize = 0, isoStringSize = 0; //, utf8StringSize = 0;
            ulong asciiStringCount = 0, unicodeStringCount = 0, isoStringCount = 0; //, utf8StringCount = 0;
            ulong compressedStringSize = 0, uncompressedStringSize = 0;
            foreach (var obj in heap.EnumerateObjectAddresses())
            {
                ClrType type = heap.GetObjectType(obj);
                // If heap corruption, continue past this object. Or if it's NOT a String we also ignore it
                if (type == null || type.IsString == false)
                    continue;

                stringObjectCounter++;
                var text = (string)type.GetValue(obj);
                var rawBytes = Encoding.Unicode.GetBytes(text);
                totalStringObjectSize += type.GetSize(obj);
                byteArraySize += (ulong)rawBytes.Length;

                VerifyStringObjectSize(runtime, type, obj, text);

                // Try each encoding in order, so we find the most-compact encoding that the text would fit in
                byte[] textAsBytes = null;
                if (IsASCII(text, out textAsBytes))
                {
                    asciiStringSize += (ulong)rawBytes.Length;
                    asciiStringCount++;

                    // ASCII is compressed as ISO-8859-1 (Latin-1) NOT ASCII
                    if (IsIsoLatin1(text, out textAsBytes))
                        compressedStringSize += (ulong)textAsBytes.Length;
                    else
                        Console.WriteLine("ERROR: \"{0}\" is ASCII but can't be encoded as ISO-8859-1 (Latin-1)", text);
                }
                // From http://stackoverflow.com/questions/7048745/what-is-the-difference-between-utf-8-and-iso-8859-1
                // "ISO 8859-1 is a single-byte encoding that can represent the first 256 Unicode characters"
                else if (IsIsoLatin1(text, out textAsBytes))
                {
                    isoStringSize += (ulong)rawBytes.Length;
                    isoStringCount++;
                    compressedStringSize += (ulong)textAsBytes.Length;
                }
                // UTF-8 and UTF-16 can both support the same range of text/character values ("Code Points"), they just store it in different ways
                // From http://stackoverflow.com/questions/4655250/difference-between-utf-8-and-utf-16/4655335#4655335
                // "Both UTF-8 and UTF-16 are variable length (multi-byte) encodings.
                // However, in UTF-8 a character may occupy a minimum of 8 bits, while in UTF-16 character length starts with 16 bits."
                //else if (IsUTF8(text, out textAsBytes))
                //{
                //    utf8StringSize += (ulong)rawBytes.Length;
                //    utf8StringCount++;
                //    compressedStringSize += (ulong)textAsBytes.Length;
                //}
                else
                {
                    unicodeStringSize += (ulong)rawBytes.Length;
                    unicodeStringCount++;
                    uncompressedStringSize += (ulong)rawBytes.Length;
                }
            }

            Console.ForegroundColor = ConsoleColor.DarkYellow;
            Console.WriteLine("\n\"System.String\" memory usage info");
            Console.ResetColor();
            Console.WriteLine("Overall {0:N0} \"System.String\" objects take up {1:N0} bytes ({2:N2} MB)",
                                stringObjectCounter, totalStringObjectSize, totalStringObjectSize / 1024.0 / 1024.0);
            Console.WriteLine("Of this underlying byte arrays (as Unicode) take up {0:N0} bytes ({1:N2} MB)",
                                byteArraySize, byteArraySize / 1024.0 / 1024.0);
            Console.WriteLine("Remaining data (object headers, other fields, etc) are {0:N0} bytes ({1:N2} MB), at {2:0.##} bytes per object\n",
                                totalStringObjectSize - byteArraySize,
                                (totalStringObjectSize - byteArraySize) / 1024.0 / 1024.0,
                                (totalStringObjectSize - byteArraySize) / (double)stringObjectCounter);

            Console.ForegroundColor = ConsoleColor.DarkYellow;
            Console.WriteLine("Actual Encoding that the \"System.String\" could be stored as (with corresponding data size)");
            Console.ResetColor();
            Console.WriteLine("  {0,15:N0} bytes ({1,8:N0} strings) as ASCII", asciiStringSize, asciiStringCount);
            Console.WriteLine("  {0,15:N0} bytes ({1,8:N0} strings) as ISO-8859-1 (Latin-1)", isoStringSize, isoStringCount);
            //Console.WriteLine("  {0,15:N0} bytes ({1,8:N0} strings) are UTF-8", utf8StringSize, utf8StringCount);
            Console.WriteLine("  {0,15:N0} bytes ({1,8:N0} strings) as Unicode", unicodeStringSize, unicodeStringCount);
            Console.WriteLine("Total: {0:N0} bytes (expected: {1:N0}{2})\n",
                                asciiStringSize + isoStringSize + unicodeStringSize, byteArraySize,
                                (asciiStringSize + isoStringSize + unicodeStringSize != byteArraySize) ? " - ERROR" : "");

            Console.ForegroundColor = ConsoleColor.DarkYellow;
            Console.WriteLine("Compression Summary:");
            Console.ResetColor();
            Console.WriteLine("  {0,15:N0} bytes Compressed (to ISO-8859-1 (Latin-1))", compressedStringSize);
            Console.WriteLine("  {0,15:N0} bytes Uncompressed (as Unicode)", uncompressedStringSize);
            Console.WriteLine("  {0,15:N0} bytes EXTRA to enable compression (1-byte field, per \"System.String\" object)", stringObjectCounter);
            var totalBytesUsed = compressedStringSize + uncompressedStringSize + stringObjectCounter;
            var totalBytesSaved = byteArraySize - totalBytesUsed;
            Console.WriteLine("\nTotal Usage:  {0:N0} bytes ({1:N2} MB), compared to {2:N0} ({3:N2} MB) before compression",
                                totalBytesUsed, totalBytesUsed / 1024.0 / 1024.0,
                                byteArraySize, byteArraySize / 1024.0 / 1024.0);
            Console.WriteLine("Total Saving: {0:N0} bytes ({1:N2} MB)\n", totalBytesSaved, totalBytesSaved / 1024.0 / 1024.0);            
        }
Example #39
0
        private static List<ClrRoot> FillRootDictionary(ClrHeap heap)
        {
            List<ClrRoot> roots = new List<ClrRoot>(heap.EnumerateRoots());
            foreach (var root in roots)
            {
                List<ClrRoot> list;
                if (!m_rootDict.TryGetValue(root.Object, out list))
                {
                    list = new List<ClrRoot>();
                    m_rootDict[root.Object] = list;
                }

                list.Add(root);
            }
            return roots;
        }
Example #40
0
 public HeapIndex(CommandExecutionContext context)
 {
     _context = context;
     _heap = context.Runtime.GetHeap();
 }
Example #41
0
 public MDHeap(ClrHeap heap)
 {
     m_heap = heap;
 }