示例#1
0
        public static int EntryPoint(string pwzArgument)
        {
            Debug.WriteLine("[KeeFarceDLL] Starting");
            //string processName = Process.GetCurrentProcess().ProcessName;
            //MessageBox.Show("The current process is " + processName + " and I am running C# code! Yuss!");

            if (is64Bit)
            {
                Debug.WriteLine("[KeeFarceDLL] Target is 64 bit");
            }

            // Retrieve the DocumentManagerEx object off the heap
            // TODO: KeePass can support multiple password files , so should probably modify this to load
            // ALL of the DocumentManagerEx's into a list and process 'em, as opposed to just breaking
            // after finding the first one.
            IntPtr docManagerPtr = IntPtr.Zero;

            using (DataTarget dataTarget = DataTarget.AttachToProcess(Process.GetCurrentProcess().Id, 5000, AttachFlag.Passive))
            {
                string     dacLocation = dataTarget.ClrVersions[0].TryGetDacLocation();
                ClrRuntime runtime     = CreateRuntimeHack(dataTarget, dacLocation, 4, 5);
                Debug.WriteLine("[KeeFarceDLL] Attached to process.");

                ClrHeap heap = runtime.GetHeap();
                foreach (ulong obj in heap.EnumerateObjects())
                {
                    ClrType type = heap.GetObjectType(obj);

                    ulong size = type.GetSize(obj);
                    if (type.Name == "KeePass.UI.DocumentManagerEx")
                    {
                        Debug.WriteLine("[KeeFarceDLL] Found DocumentManagerEx at: " + obj.ToString("X") + " " + type.Name);
                        docManagerPtr = (IntPtr)obj;
                        break;
                    }
                }

                if (docManagerPtr == IntPtr.Zero)
                {
                    // Didn't find a document manager, time to return.
                    Debug.WriteLine("[KeeFarceDLL] No DocumentManagerEx found");
                    return(1);
                }
            }

            // Get the DocumentManagerEx object
            Converter <object> ptrconv           = new Converter <object>();
            object             documentManagerEx = ptrconv.ConvertFromIntPtr(docManagerPtr);
            var info = new DocumentManagerExInfo(documentManagerEx);
            int r    = doExport(info.ActiveDatabase, info.RootGroup, exportFile);

            return(r);
        }
示例#2
0
        /// <summary>
        /// Taken from https://github.com/Microsoft/dotnetsamples/blob/master/Microsoft.Diagnostics.Runtime/CLRMD/docs/WalkingTheHeap.md
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="count"></param>
        /// <param name="size"></param>
        static protected void GetObjSize(ClrHeap heap, ulong obj, ObjectSet farReachingParents, out uint count, out ulong size)
        {
            // Evaluation stack
            Stack <ulong> 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.  Note the ObjectSet here is basically just "HashSet<ulong>".
            // However, HashSet<ulong> is *extremely* memory inefficient.  So we use our own to
            // avoid OOMs.
            ObjectSet considered = new ObjectSet(heap);

            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 (farReachingParents.Contains(obj))
                {
                    continue;
                }

                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;
                }

                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, delegate(ulong child, int offset)
                {
                    if (child != 0 && !considered.Contains(child) && !farReachingParents.Contains(child))
                    {
                        eval.Push(child);
                    }
                });
            }
        }
示例#3
0
        private bool FilterObject(ulong obj, ulong mt)
        {
            bool    match = true;
            ClrType type  = null;

            if (!String.IsNullOrEmpty(TypeRegex))
            {
                type = _heap.GetObjectType(obj);
                if (type == null || String.IsNullOrEmpty(type.Name))
                {
                    match = false;
                }

                if (match)
                {
                    // TODO Consider compiling the regex
                    match = Regex.IsMatch(type.Name, TypeRegex);
                }
            }

            if (match && MinSize != -1)
            {
                type  = type ?? _heap.GetObjectType(obj);
                match = (long)type.GetSize(obj) >= MinSize;
            }
            if (match && MaxSize != -1)
            {
                type  = type ?? _heap.GetObjectType(obj);
                match = (long)type.GetSize(obj) <= MaxSize;
            }

            if (match && MethodTable != 0)
            {
                match = MethodTable == mt;
            }

            return(match);
        }
示例#4
0
        private void StoreData(CancellationToken token)
        {
            BeginUpdate();
            Dictionary <ClrType, ClrTypeStats> stats = new Dictionary <ClrType, ClrTypeStats>();

            foreach (var address in ClrDump.Heap.EnumerateObjectAddresses())
            {
                ClrType type = ClrDump.Heap.GetObjectType(address);
                if (type == null)
                {
                    continue;
                }
                ulong size = type.GetSize(address);

                ClrTypeStats stat;
                if (!stats.TryGetValue(type, out stat))
                {
                    stat        = new ClrTypeStats(stats.Count, type);
                    stats[type] = stat;
                }

                stat.Inc(size);
                InsertInstances(stat.Id, address);

                type.EnumerateRefsOfObject(address, delegate(ulong child, int offset)
                {
                    InsertReferences(child, address);
                });

                n++;
                if (n % 1024 * 64 == 0)
                {
                    if (token.IsCancellationRequested)
                    {
                        return;
                    }
                    ClrDump.MessageBus.Status(GetStats());
                }
            }


            ClrDump.MessageBus.Log(this, "Inserting type stats...");
            foreach (var stat in stats.Values)
            {
                InsertTypeStat(stat);
            }

            EndUpdate();
            ClrDump.MessageBus.Status("Cache Initialized.", StatusType.EndTask);
        }
        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);
                    }
                });
            }
        }
示例#6
0
        private static SortedDictionary <string, ManagedObject> ListObjects(ClrRuntime runtime)
        {
            SortedDictionary <String, ManagedObject> managedObjects = new SortedDictionary <string, ManagedObject>();

            if (runtime.Heap.CanWalkHeap)
            {
                foreach (ulong ptr in runtime.Heap.EnumerateObjectAddresses())
                {
                    ClrType type = runtime.Heap.GetObjectType(ptr);

                    //Free objects are not real objects in the strictest sense. They are actually markers placed by the GC to
                    //denote free space on the heap. Free objects have no fields (though they do have a size). In general, if
                    //you are trying to find heap fragmentation, you will need to take a look at how many Free objects there are,
                    //how big they are, and what lies between them. Otherwise, you should ignore them.
                    //https://github.com/Microsoft/clrmd/blob/master/Documentation/TypesAndFields.md
                    if (type == null || type.IsFree)
                    {
                        continue;
                    }

                    ManagedObject mo = null;
                    if (!managedObjects.ContainsKey(type.Name))
                    {
                        mo = new ManagedObject()
                        {
                            ObjectName = type.Name
                        };
                        managedObjects.Add(type.Name, mo);
                    }

                    if (mo == null)
                    {
                        mo = managedObjects[type.Name];
                    }

                    mo.ObjectCount++;
                    mo.ObjectSize += type.GetSize(ptr);
                }
            }
            return(managedObjects);
        }
        public void Add(ulong candidateAddress, [NotNull] ClrType type)
        {
            if (candidateAddress == 0)
            {
                return;
            }

            Assert.ArgumentNotNull(type, "type");
            HeapTypeStatisticsEntry existing = Get(type.MetadataToken);

            var size = (long)type.GetSize(candidateAddress);

            if (existing == null)
            {
                var added = new HeapTypeStatisticsEntry(size, type);
                typeStats.Add(type.MetadataToken, added);
                return;
            }

            existing.AddTypeUsage(size);
        }
        private void treeViewObjects_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            if (e.Node.Nodes.Count == 1 && e.Node.Nodes[0].Tag == null)
            {
                e.Node.Nodes.Clear();
                ClrTypeHelper c = (ClrTypeHelper)e.Node.Tag;

                ClrType type = runtime.Heap.GetObjectType(c.Ptr);
                foreach (ClrObject o in type.EnumerateObjectReferences(c.Ptr))
                {
                    if (o.Type.Name == "System.String")
                    {
                        continue;
                    }

                    ClrType refType = runtime.Heap.GetObjectType(o.Address);

                    TreeNode refNode = new TreeNode(refType.Name);
                    refNode.Nodes.Add(new TreeNode());
                    ClrTypeHelper refHelper = new ClrTypeHelper()
                    {
                        Ptr      = o.Address,
                        Name     = refType.Name,
                        Size     = type.GetSize(o.Address),
                        TreeNode = refNode
                    };

                    System.Diagnostics.Debug.WriteLine("{0:X} {1}", o.Address, refType.Name);
                    refNode.Tag = refHelper;
                    e.Node.Nodes.Add(refNode);
                    globalSearchList.Add(refHelper);
                }

                foreach (ClrInstanceField f in type.Fields)
                {
                    System.Diagnostics.Debug.WriteLine("{0:X} {1}", f.GetAddress(c.Ptr), f.Type);
                }
            }
        }
示例#9
0
        private static void PrintManagedObjects(ClrRuntime runtime)
        {
            if (!runtime.Heap.CanWalkHeap)
            {
                Console.WriteLine("Cannot walk the heap!");
            }
            else
            {
                foreach (ulong obj in runtime.Heap.EnumerateObjectAddresses())
                {
                    ClrType type = runtime.Heap.GetObjectType(obj);

                    // If heap corruption, continue past this object.
                    if (type == null)
                    {
                        continue;
                    }

                    ulong size = type.GetSize(obj);
                    LogHelper.Logger.InfoFormat("{0,12:X} {1,8:n0} {2,1:n0} {3}", obj, size, runtime.Heap.GetGeneration(obj), type.Name);
                }
            }
        }
示例#10
0
        //TODO serialize this properly
        public void InitMemoryStat()
        {
            if (this.context.Runtime != null && this.context.Heap != null)
            {
                foreach (var obj in this.context.Heap.EnumerateObjectAddresses())
                {
                    ulong value;

                    // get value at pointer
                    this.context.Runtime.ReadPointer(obj, out value);

                    ClrType type = this.context.Heap.GetObjectType(obj);
                    if (type == null || type.IsFree)
                    {
                        continue;
                    }

                    // needs obj reference, because types can be variable sized in CLR!
                    ulong size = type.GetSize(obj);

                    if (memDict.ContainsKey(value))
                    {
                        memDict[value].Count++;
                        memDict[value].Size += size;
                    }
                    else
                    {
                        memDict.Add(value, new SDMemoryObject {
                            Count = 1,
                            Size  = size,
                            Type  = string.IsNullOrEmpty(type.Name) ? "Unknown" : type.Name
                        }
                                    );
                    }
                }
            }
        }
示例#11
0
        private static HeapSnapshot Compute(ClrHeap heap)
        {
            var snapshot = new HeapSnapshot();

            foreach (ulong objAddress in heap.EnumerateObjectAddresses())
            {
                ClrType type = heap.GetObjectType(objAddress);
                if (type == null)
                {
                    continue;
                }

                var mt   = type.MethodTable.ToString();
                var name = type.Name;
                var key  = HeapSnapshot.GetKey(name, mt);

                if (!snapshot.TypeStats.TryGetValue(key, out var entry))
                {
                    entry = new TypeEntry()
                    {
                        Name        = name,
                        MethodTable = mt
                    };

                    snapshot.TypeStats[key] = entry;
                }
                entry.Count          = entry.Count + 1;
                snapshot.ObjectCount = snapshot.ObjectCount + 1;

                var size = type.GetSize(objAddress);
                entry.TotalSize = entry.TotalSize + (long)size;
                snapshot.Size   = snapshot.Size + (long)size;
            }

            return(snapshot);
        }
示例#12
0
文件: Form1.cs 项目: VE-2016/VE-2016
        static Dictionary <ClrType, Entry> DumpHeap(ClrRuntime runtime)
        {
            Dictionary <ClrType, Entry> stats = new Dictionary <ClrType, Entry>();



            try
            {
                // Create a ClrRuntime instance from the dump and dac location.  The ClrRuntime
                // object represents a version of CLR loaded in the process.  It contains data
                // such as the managed threads in the process, the AppDomains in the process,
                // the managed heap, and so on.
                //ClrRuntime runtime = CreateRuntime(dump, dac);

                // Walk the entire heap and build heap statistics in "stats".



                // This is the way to walk every object on the heap:  Get the ClrHeap instance
                // from the runtime.  Walk every segment in heap.Segments, and use
                // ClrSegment.FirstObject and ClrSegment.NextObject to iterate through
                // objects on that segment.
                ClrHeap heap = runtime.GetHeap();
                foreach (ClrSegment seg in heap.Segments)
                {
                    for (ulong obj = seg.FirstObject; obj != 0; obj = seg.NextObject(obj))
                    {
                        // This gets the type of the object.
                        ClrType type = heap.GetObjectType(obj);

                        if (type == null)
                        {
                            continue;
                        }

                        ulong size = type.GetSize(obj);


                        //objs[obj] = type;


                        // If the user didn't request "-stat", print out the object.

                        //    Console.WriteLine("{0,16:X} {1,12:n0} {2}", obj, size, type.Name);

                        // Add an entry to the dictionary, if one doesn't already exist.
                        Entry entry = null;

                        if (!stats.TryGetValue(type, out entry))
                        {
                            entry      = new Entry();
                            entry.Name = type.Name;
                            entry.refs.Add(obj);
                            //entry.obj = obj;
                            stats[type] = entry;
                        }
                        else
                        {
                            //entry.obj = obj;
                            entry.refs.Add(obj);
                        }
                        // Update the statistics for this object.
                        entry.Count++;
                        entry.Size += type.GetSize(obj);


                        //type.EnumerateRefsOfObject(obj, delegate (ulong child, int offset)
                        //{
                        //    objs[obj] = child;
                        //});
                    }
                }

                // Now print out statistics.

                //    Console.WriteLine();

                // We'll actually let linq do the heavy lifting.
                var sortedStats = from entry in stats.Values
                                  orderby entry.Size
                                  select entry;

                //Console.WriteLine("{0,12} {1,12} {2}", "Size", "Count", "Type");
                //foreach (var entry in sortedStats)
                //    Console.WriteLine("{0,12:n0} {1,12:n0} {2}", entry.Size, entry.Count, entry.Name);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Unhandled exception:");
                Console.WriteLine(ex);
            }
            finally
            {
            }
            return(stats);
        }
示例#13
0
        private static (uint, ulong) PopulateReferencedObjects(ClrHeap heap, ClrObjectModel clrObjModel)
        {
            // Evaluation stack
            var eval = new Stack <ulong>();
            var addressToClrObjectModel = new Dictionary <ulong, ClrObjectModel>
            {
                { clrObjModel.Address, clrObjModel }
            };
            // To make sure we don't count the same object twice, we'll keep a set of all objects
            // we've seen before.  Note the ObjectSet here is basically just "HashSet<ulong>".
            // However, HashSet<ulong> is *extremely* memory inefficient.  So we use our own to
            // avoid OOMs.
            var   currentObj = clrObjModel.Address;
            var   considered = new ObjectSet(heap);
            uint  count      = 0;
            ulong size       = 0;

            eval.Push(currentObj);

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

                considered.Add(currentObj);

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

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

                // Now enumerate all objects that this object points to, add them to the
                // evaluation stack if we haven't seen them before.
                type.EnumerateRefsOfObject(currentObj, delegate(ulong child, int offset)
                {
                    if (child != 0 && !considered.Contains(child))
                    {
                        var childObj = heap.GetObject(child);
                        ClrObjectModel childClrModel = null;
                        if (addressToClrObjectModel.ContainsKey(childObj))
                        {
                            childClrModel = addressToClrObjectModel[childObj];
                        }
                        else
                        {
                            childClrModel = new ClrObjectModel
                            {
                                TypeName          = childObj.Type.Name,
                                Address           = childObj,
                                ReferencedObjects = new List <ClrObjectModel>(),
                            };
                            addressToClrObjectModel[currentObj] = childClrModel;
                        }

                        addressToClrObjectModel[currentObj].ReferencedObjects.Add(childClrModel);
                        eval.Push(child);
                    }
                });
            }

            return(count, size);
        }
示例#14
0
        public void OptimizedClassHistogram()
        {
            using (DataTarget dt = TestTargets.Types.LoadFullDump())
            {
                ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();
                ClrHeap    heap    = runtime.Heap;

                // ensure that the optimized version is faster than the default one
                Stopwatch timing = new Stopwatch();
                var       notOptimizedStatistics  = new Dictionary <ClrType, TypeEntry>(32768);
                int       notOptimizedObjectCount = 0;

                // with an optimized version
                timing.Start();

                foreach (var objDetails in heap.EnumerateObjectDetails())
                {
                    ClrType type = objDetails.Item3;
                    ulong   size = objDetails.Item4;

                    TypeEntry entry;
                    if (!notOptimizedStatistics.TryGetValue(type, out entry))
                    {
                        entry = new TypeEntry()
                        {
                            TypeName = type.Name,
                            Size     = 0
                        };
                        notOptimizedStatistics[type] = entry;
                    }
                    entry.Count++;
                    entry.Size += size;
                    notOptimizedObjectCount++;
                }

                timing.Stop();
                var notOptimizedTime = TimeSpan.FromMilliseconds(timing.ElapsedMilliseconds);


                // with an non-optimized version
                var statistics  = new Dictionary <ClrType, TypeEntry>(32768);
                int objectCount = 0;
                timing.Restart();

                foreach (ulong objAddress in heap.EnumerateObjectAddresses())
                {
                    ClrType type = heap.GetObjectType(objAddress);
                    ulong   size = type.GetSize(objAddress);

                    TypeEntry entry;
                    if (!statistics.TryGetValue(type, out entry))
                    {
                        entry = new TypeEntry()
                        {
                            TypeName = type.Name,
                            Size     = 0
                        };
                        statistics[type] = entry;
                    }
                    entry.Count++;
                    entry.Size += size;
                    objectCount++;
                }

                timing.Stop();

                // check object count
                Assert.AreEqual(notOptimizedObjectCount, objectCount);

                // check heap content
                var types = notOptimizedStatistics.Keys;
                foreach (var type in types)
                {
                    var notOptimizedDetails = notOptimizedStatistics[type];
                    var details             = statistics[type];

                    Assert.AreEqual(notOptimizedDetails.TypeName, details.TypeName);
                    Assert.AreEqual(notOptimizedDetails.Count, details.Count);
                    Assert.AreEqual(notOptimizedDetails.Size, details.Size);
                }
                Assert.AreEqual(types.Count, statistics.Count);

                // checking that optimized is faster could be flaky
                // Assert.IsTrue(notOptimizedTime > TimeSpan.FromMilliseconds(timing.ElapsedMilliseconds));
            }
        }
示例#15
0
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (IsNull())
            {
                result = new ClrNullValue(m_heap);
                return(true);
            }

            if (binder.Name == "__Size")
            {
                result = m_type.GetSize(m_addr);
                return(true);
            }

            if (binder.Name == "__Type")
            {
                result = m_type.Name;
                return(true);
            }

            if (binder.Name == "__Address")
            {
                result = String.Format("{0:x16}", m_addr);
                return(true);
            }

            if (binder.Name == "__Fields")
            {
                result = (from f in m_type.Fields where f.Type != null select new { Name = f.Name, Type = f.Type.Name }).ToArray();
                return(true);
            }

            ClrInstanceField field = null;

            foreach (var instanceField in m_type.Fields)
            {
                // Auto-generated properties have this ugly <> thing around their fields that you can't put
                // in a C# expression. Clean them up to make them accessible by their property name.
                var cleanFieldName = instanceField.Name;
                if (cleanFieldName.StartsWith("<") && cleanFieldName.EndsWith(">k__BackingField"))
                {
                    cleanFieldName = cleanFieldName.Substring(
                        1, cleanFieldName.Length - (1 + ">k__BackingField".Length));
                }
                if (cleanFieldName == binder.Name)
                {
                    field = instanceField;
                    break;
                }
            }

            if (field == null)
            {
                if (ClrDynamicClass.GetStaticField(m_heap, m_type, binder, out result))
                {
                    return(true);
                }

                throw new InvalidOperationException(string.Format("Type '{0}' does not contain a '{1}' field.", m_type.Name, binder.Name));
            }

            if (field.IsPrimitive())
            {
                object value = field.GetValue(m_addr, m_inner);
                if (value == null)
                {
                    result = new ClrNullValue(m_heap);
                }
                else
                {
                    result = new ClrPrimitiveValue(value, field.ElementType);
                }

                return(true);
            }
            else if (field.IsValueClass())
            {
                ulong addr = field.GetAddress(m_addr, m_inner);
                result = new ClrObject(m_heap, field.Type, addr, true);
                return(true);
            }
            else if (field.ElementType == ClrElementType.String)
            {
                ulong addr = field.GetAddress(m_addr, m_inner);
                if (!m_heap.GetRuntime().ReadPointer(addr, out addr))
                {
                    result = new ClrNullValue(m_heap);
                    return(true);
                }

                result = new ClrObject(m_heap, field.Type, addr);
                return(true);
            }
            else
            {
                object value = field.GetValue(m_addr, m_inner);
                if (value == null)
                {
                    result = new ClrNullValue(m_heap);
                }
                else
                {
                    result = new ClrObject(m_heap, field.Type, (ulong)value);
                }

                return(true);
            }
        }
示例#16
0
        public override ulong GetSize(ulong objRef)
        {
            ClrType realType = DesktopHeap.GetObjectType(objRef);

            return(realType.GetSize(objRef));
        }
示例#17
0
 /// <summary>
 ///     GetSize returns the size in bytes for the total overhead of the object 'objRef'.
 /// </summary>
 /// <param name="objRef">The object reference.</param>
 /// <returns>System.UInt64.</returns>
 public ulong GetSize(ulong objRef) => ClrType.GetSize(objRef);
示例#18
0
        static void Main(string[] args)
        {
            bool   stat, live;
            string dump, dac;

            if (!TryParseArgs(args, out dump, out dac, out stat, out live))
            {
                Usage();
                Environment.Exit(1);
            }

            try
            {
                ClrRuntime runtime = CreateRuntime(dump, dac);
                ClrHeap    heap    = runtime.GetHeap();

                ObjectSet liveObjs = null;
                if (live)
                {
                    liveObjs = GetLiveObjects(heap);
                }

                Dictionary <ClrType, Entry> stats = new Dictionary <ClrType, Entry>();

                if (!stat)
                {
                    Console.WriteLine("{0,16} {1,12} {2}", "Object", "Size", "Type");
                }

                foreach (ClrSegment seg in heap.Segments)
                {
                    for (ulong obj = seg.FirstObject; obj != 0; obj = seg.NextObject(obj))
                    {
                        if (live && !liveObjs.Contains(obj))
                        {
                            continue;
                        }

                        // This gets the type of the object.
                        ClrType type = heap.GetObjectType(obj);
                        ulong   size = type.GetSize(obj);

                        // If the user didn't request "-stat", print out the object.
                        if (!stat)
                        {
                            Console.WriteLine("{0,16:X} {1,12:n0} {2}", obj, size, type.Name);
                        }

                        // Add an entry to the dictionary, if one doesn't already exist.
                        Entry entry = null;
                        if (!stats.TryGetValue(type, out entry))
                        {
                            entry       = new Entry();
                            entry.Name  = type.Name;
                            stats[type] = entry;
                        }

                        // Update the statistics for this object.
                        entry.Count++;
                        entry.Size += type.GetSize(obj);
                    }
                }

                // Now print out statistics.
                if (!stat)
                {
                    Console.WriteLine();
                }

                // We'll actually let linq do the heavy lifting.
                var sortedStats = from entry in stats.Values
                                  orderby entry.Size
                                  select entry;

                ulong totalSize = 0, totalCount = 0;
                Console.WriteLine("{0,12} {1,12} {2}", "Size", "Count", "Type");
                foreach (var entry in sortedStats)
                {
                    Console.WriteLine("{0,12:n0} {1,12:n0} {2}", entry.Size, entry.Count, entry.Name);
                    totalSize  += entry.Size;
                    totalCount += (uint)entry.Count;
                }

                Console.WriteLine();
                Console.WriteLine("Total: {0:n0} bytes in {1:n0} objects", totalSize, totalCount);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Unhandled exception:");
                Console.WriteLine(ex);
            }
        }
示例#19
0
        private void InspectProcess(int pId)
        {
            using (DataTarget target = DataTarget.AttachToProcess(pId, 10000))
            {
                ShowCLRRuntimeInformation(target);

                ClrRuntime runtime = target.ClrVersions.First().CreateRuntime();

                LoadThreads(runtime);

                Dictionary <string, TypeEntry>   types       = new Dictionary <string, TypeEntry>();
                Dictionary <string, StringInfor> stringCount = new Dictionary <string, StringInfor>();

                ClrHeap heap = runtime.Heap;

                var finalizerQueueObjects = runtime.EnumerateFinalizerQueueObjectAddresses().ToList();
                var pinnedObjects         = runtime.EnumerateHandles().Where(h => h.IsPinned).Select(h => h.Object).ToList();
                var blockingObjects       = heap.EnumerateBlockingObjects().Select(x => x.Object).ToList();
                //var blockingObjects = runtime.Threads.SelectMany(x => x.BlockingObjects).Select(x => x.Object).ToList();

                foreach (ulong obj in heap.EnumerateObjects())
                {
                    ClrType type = heap.GetObjectType(obj);
                    var     size = type.GetSize(obj);
                    var     gen  = heap.GetGeneration(obj);
                    var     isInFinalizerQueue = finalizerQueueObjects.Contains(obj);
                    var     isPinned           = pinnedObjects.Contains(obj);
                    var     isBlocking         = blockingObjects.Contains(obj);

                    if (types.ContainsKey(type.Name))
                    {
                        types[type.Name].Count++;
                        types[type.Name].MinSize              = Math.Min(types[type.Name].MinSize, size);
                        types[type.Name].MaxSize              = Math.Max(types[type.Name].MaxSize, size);
                        types[type.Name].TotalSize           += size;
                        types[type.Name].Generation0         += gen == 0 ? 1 : 0;
                        types[type.Name].Generation1         += gen == 1 ? 1 : 0;
                        types[type.Name].Generation2         += gen == 2 ? 1 : 0;
                        types[type.Name].FinalizerQueueCount += isInFinalizerQueue ? 1 : 0;
                        types[type.Name].PinnedCount         += isPinned ? 1 : 0;
                        types[type.Name].BlockingCount       += isBlocking ? 1 : 0;
                    }
                    else
                    {
                        types[type.Name] = new TypeEntry
                        {
                            Name                = type.Name,
                            Count               = 1,
                            MinSize             = size,
                            MaxSize             = size,
                            TotalSize           = size,
                            Generation0         = gen == 0 ? 1 : 0,
                            Generation1         = gen == 1 ? 1 : 0,
                            Generation2         = gen == 2 ? 1 : 0,
                            FinalizerQueueCount = isInFinalizerQueue ? 1 : 0,
                            PinnedCount         = isPinned ? 1 : 0,
                            BlockingCount       = isBlocking ? 1 : 0,
                        };
                    }

                    if (type.IsString)
                    {
                        var text = (string)type.GetValue(obj);

                        if (stringCount.ContainsKey(text))
                        {
                            stringCount[text].Count++;
                            stringCount[text].Generation0 += gen == 0 ? 1 : 0;
                            stringCount[text].Generation1 += gen == 1 ? 1 : 0;
                            stringCount[text].Generation2 += gen == 2 ? 1 : 0;
                        }
                        else
                        {
                            stringCount[text] = new StringInfor
                            {
                                Text        = text,
                                Count       = 1,
                                Generation0 = gen == 0 ? 1 : 0,
                                Generation1 = gen == 1 ? 1 : 0,
                                Generation2 = gen == 2 ? 1 : 0,
                            };
                        }
                    }
                }

                var sortOrder = heapObjectsGrid.SortOrder == SortOrder.Ascending ?
                                ListSortDirection.Ascending : ListSortDirection.Descending;
                var sortCol = heapObjectsGrid.SortedColumn;

                int rowcount = 0;
                heapObjectsGrid.Rows.Clear();
                foreach (var val in types.Where(x => x.Value.Count > 1))
                {
                    var             infor   = val.Value;
                    DataGridViewRow gridrow = new DataGridViewRow();
                    gridrow.DefaultCellStyle.SelectionBackColor = Color.Black;
                    if (rowcount % 2 > 0)
                    {
                        gridrow.DefaultCellStyle.BackColor = Color.AliceBlue;
                    }
                    rowcount++;

                    DataGridViewTextBoxCell name = new DataGridViewTextBoxCell();
                    name.Value = infor.Name;
                    gridrow.Cells.Add(name);

                    DataGridViewTextBoxCell count = new DataGridViewTextBoxCell();
                    count.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    count.Style.Format    = "n0";
                    count.Value           = infor.Count;
                    gridrow.Cells.Add(count);

                    DataGridViewTextBoxCell minSize = new DataGridViewTextBoxCell();
                    minSize.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    minSize.Style.Format    = "n0";
                    if (infor.MinSize >= 85000)
                    {
                        minSize.Style.ForeColor = Color.Orange;
                        minSize.ToolTipText     = "Large Object Heap";
                    }
                    minSize.Value = infor.MinSize;
                    gridrow.Cells.Add(minSize);

                    DataGridViewTextBoxCell maxSize = new DataGridViewTextBoxCell();
                    maxSize.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    maxSize.Style.Format    = "n0";
                    if (infor.MaxSize >= 85000)
                    {
                        maxSize.Style.ForeColor = Color.Orange;
                        maxSize.ToolTipText     = "Large Object Heap";
                    }
                    maxSize.Value = infor.MaxSize;
                    gridrow.Cells.Add(maxSize);

                    DataGridViewTextBoxCell totalSize = new DataGridViewTextBoxCell();
                    totalSize.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    totalSize.Style.Format    = "n0";
                    totalSize.Value           = infor.TotalSize;
                    gridrow.Cells.Add(totalSize);

                    DataGridViewTextBoxCell generation0 = new DataGridViewTextBoxCell();
                    generation0.Value           = infor.Generation0;
                    generation0.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    generation0.Style.Format    = "n0";
                    gridrow.Cells.Add(generation0);

                    DataGridViewTextBoxCell generation1 = new DataGridViewTextBoxCell();
                    generation1.Value           = infor.Generation1;
                    generation1.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    generation1.Style.Format    = "n0";
                    gridrow.Cells.Add(generation1);

                    DataGridViewTextBoxCell generation2 = new DataGridViewTextBoxCell();
                    generation2.Value           = infor.Generation2;
                    generation2.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    generation2.Style.Format    = "n0";
                    gridrow.Cells.Add(generation2);

                    DataGridViewTextBoxCell finalizerQueue = new DataGridViewTextBoxCell();
                    finalizerQueue.Value           = infor.FinalizerQueueCount;
                    finalizerQueue.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    finalizerQueue.Style.Format    = "n0";
                    gridrow.Cells.Add(finalizerQueue);

                    DataGridViewTextBoxCell pinned = new DataGridViewTextBoxCell();
                    pinned.Value           = infor.PinnedCount;
                    pinned.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    pinned.Style.Format    = "n0";
                    gridrow.Cells.Add(pinned);

                    DataGridViewTextBoxCell blocking = new DataGridViewTextBoxCell();
                    blocking.Value           = infor.BlockingCount;
                    blocking.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    blocking.Style.Format    = "n0";
                    gridrow.Cells.Add(blocking);

                    heapObjectsGrid.Rows.Add(gridrow);
                }

                heapObjectsGrid.Columns[1].HeaderCell.ToolTipText = $"Total: { types.Values.Sum(x => x.Count).ToString("N0")} objects";
                heapObjectsGrid.Columns[4].HeaderCell.ToolTipText = $"Total: {types.Values.Sum(x => (long)x.TotalSize).ToString("N0")} bytes";

                if (sortCol != null)
                {
                    heapObjectsGrid.Sort(sortCol, sortOrder);
                }

                // Strings Grid View:
                rowcount = 0;
                stringsGrid.Rows.Clear();
                foreach (var str in stringCount)
                {
                    DataGridViewRow gridrow = new DataGridViewRow();
                    gridrow.DefaultCellStyle.SelectionBackColor = Color.Black;
                    if (rowcount % 2 > 0)
                    {
                        gridrow.DefaultCellStyle.BackColor = Color.AliceBlue;
                    }
                    rowcount++;

                    DataGridViewTextBoxCell name = new DataGridViewTextBoxCell();
                    name.Value = str.Key;
                    gridrow.Cells.Add(name);

                    DataGridViewTextBoxCell length = new DataGridViewTextBoxCell();
                    length.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    length.Style.Format    = "n0";
                    length.Value           = str.Key.Length;
                    gridrow.Cells.Add(length);

                    DataGridViewTextBoxCell count = new DataGridViewTextBoxCell();
                    count.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    count.Style.Format    = "n0";
                    count.Value           = str.Value.Count;
                    gridrow.Cells.Add(count);

                    DataGridViewTextBoxCell generation0 = new DataGridViewTextBoxCell();
                    generation0.Value           = str.Value.Generation0;
                    generation0.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    generation0.Style.Format    = "n0";
                    gridrow.Cells.Add(generation0);

                    DataGridViewTextBoxCell generation1 = new DataGridViewTextBoxCell();
                    generation1.Value           = str.Value.Generation1;
                    generation1.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    generation1.Style.Format    = "n0";
                    gridrow.Cells.Add(generation1);

                    DataGridViewTextBoxCell generation2 = new DataGridViewTextBoxCell();
                    generation2.Value           = str.Value.Generation2;
                    generation2.Style.Alignment = DataGridViewContentAlignment.BottomRight;
                    generation2.Style.Format    = "n0";
                    gridrow.Cells.Add(generation2);

                    stringsGrid.Rows.Add(gridrow);
                }
            }
        }
示例#20
0
 public void GetSize(ulong objRef, out ulong pSize)
 {
     pSize = m_type.GetSize(objRef);
 }
示例#21
0
        /// <summary>
        /// Find all Strings in Heap an generate a dublicate string report
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonStrings_Click(object sender, EventArgs e)
        {
            if (Process == null)
            {
                return;
            }

            saveFileDialogStrings.FileName = String.Format("clrmd_{0:yyyyMMdd_HHmmss}", DateTime.Now);
            if (saveFileDialogStrings.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            if (File.Exists(saveFileDialogStrings.FileName))
            {
                File.Delete(saveFileDialogStrings.FileName);
            }

            Cursor.Current = Cursors.WaitCursor;

            HashSet <StringObjectHelper> stringObjectList = new HashSet <StringObjectHelper>();
            ulong fullSize    = 0;
            int   objectCount = 0;

            using (StreamWriter writer = new StreamWriter(saveFileDialogStrings.FileName, true, Encoding.UTF8))
            {
                using (DataTarget dataTarget = DataTarget.AttachToProcess(Process.Id, dataTargetTimeOut, dataTargetAttachFlag))
                {
                    ClrInfo    clrVersion = dataTarget.ClrVersions.First();
                    ClrRuntime runtime    = clrVersion.CreateRuntime();
                    if (runtime.Heap.CanWalkHeap)
                    {
                        foreach (ulong ptr in runtime.Heap.EnumerateObjectAddresses())
                        {
                            ClrType type = runtime.Heap.GetObjectType(ptr);

                            if (type == null || type.IsString == false)
                            {
                                continue;
                            }

                            StringObjectHelper stringObject = new StringObjectHelper();
                            stringObject.String = (string)type.GetValue(ptr);
                            stringObject.Size   = type.GetSize(ptr);

                            StringObjectHelper stringObjectFound;
                            if (stringObjectList.TryGetValue(stringObject, out stringObjectFound))
                            {
                                stringObjectFound.PtrList.Add(ptr);
                            }
                            else
                            {
                                stringObject.PtrList.Add(ptr);
                                stringObjectList.Add(stringObject);
                            }
                            objectCount++;
                            fullSize += stringObject.Size;

                            //write all strings
                            writer.WriteLine("**{0}#{1:X}#G{2}#{3:n0}",
                                             objectCount,
                                             ptr,
                                             type.Heap.GetGeneration(ptr),
                                             stringObject.Size);

                            writer.WriteLine(stringObject.String);
                        }
                    }

                    writer.WriteLine();
                    writer.WriteLine("**Position#HeapPtr#Generation#Size");
                    writer.WriteLine();
                    writer.WriteLine("{0:n0} String Objects", objectCount);
                    writer.WriteLine("{0:n0} String unique Strings", stringObjectList.Count);
                    writer.WriteLine("{0:n0} Bytes", fullSize);
                }
            }

            //write dublicate info
            var orderedList = stringObjectList.OrderByDescending(x => x.PtrList.Count);

            using (StreamWriter writer = new StreamWriter(saveFileDialogStrings.FileName + ".unique.csv", true, Encoding.UTF8))
            {
                writer.WriteLine("Count;Size;FullSize;Content;Ptrs");
                foreach (StringObjectHelper so in orderedList)
                {
                    string pointerList = String.Join(",", so.PtrList.Select(x => String.Format("x{0:X}", x)));
                    writer.WriteLine(String.Format("{0};{1};{2};{3};{4}",
                                                   so.PtrList.Count,
                                                   so.Size,
                                                   so.Size * (ulong)so.PtrList.Count,
                                                   (so.String.Length > 50 ? so.String.Substring(0, 50) + " ..." : so.String).Replace("'", "").Replace(";", "").Replace("\r", " ").Replace("\n", ""),
                                                   pointerList.Length > 50 ? pointerList.Substring(0, 50) + " ..." : pointerList));
                }
            }

            Cursor.Current = Cursors.Default;
        }
示例#22
0
        static void Main(string[] args)
        {
            bool   stat;
            string dump, dac;

            if (!TryParseArgs(args, out dump, out dac, out stat))
            {
                Usage();
                Environment.Exit(1);
            }

            try
            {
                // Create a ClrRuntime instance from the dump and dac location.  The ClrRuntime
                // object represents a version of CLR loaded in the process.  It contains data
                // such as the managed threads in the process, the AppDomains in the process,
                // the managed heap, and so on.
                ClrRuntime runtime = CreateRuntime(dump, dac);

                // Walk the entire heap and build heap statistics in "stats".
                Dictionary <ClrType, Entry> stats = new Dictionary <ClrType, Entry>();

                if (!stat)
                {
                    Console.WriteLine("{0,16} {1,12} {2}", "Object", "Size", "Type");
                }

                // This is the way to walk every object on the heap:  Get the ClrHeap instance
                // from the runtime.  Walk every segment in heap.Segments, and use
                // ClrSegment.FirstObject and ClrSegment.NextObject to iterate through
                // objects on that segment.
                ClrHeap heap = runtime.GetHeap();
                foreach (ClrSegment seg in heap.Segments)
                {
                    for (ulong obj = seg.FirstObject; obj != 0; obj = seg.NextObject(obj))
                    {
                        // This gets the type of the object.
                        ClrType type = heap.GetObjectType(obj);
                        ulong   size = type.GetSize(obj);

                        // If the user didn't request "-stat", print out the object.
                        if (!stat)
                        {
                            Console.WriteLine("{0,16:X} {1,12:n0} {2}", obj, size, type.Name);
                        }

                        // Add an entry to the dictionary, if one doesn't already exist.
                        Entry entry = null;
                        if (!stats.TryGetValue(type, out entry))
                        {
                            entry       = new Entry();
                            entry.Name  = type.Name;
                            stats[type] = entry;
                        }

                        // Update the statistics for this object.
                        entry.Count++;
                        entry.Size += type.GetSize(obj);
                    }
                }

                // Now print out statistics.
                if (!stat)
                {
                    Console.WriteLine();
                }

                // We'll actually let linq do the heavy lifting.
                var sortedStats = from entry in stats.Values
                                  orderby entry.Size
                                  select entry;

                Console.WriteLine("{0,12} {1,12} {2}", "Size", "Count", "Type");
                foreach (var entry in sortedStats)
                {
                    Console.WriteLine("{0,12:n0} {1,12:n0} {2}", entry.Size, entry.Count, entry.Name);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Unhandled exception:");
                Console.WriteLine(ex);
            }
        }
        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);
        }
示例#24
0
        private static void RunApplication(CommandLineOptions opts)
        {
            if (opts.PID == 0 && String.IsNullOrEmpty(opts.ProcessName))
            {
                ShowHelp(null);
                return;
            }
            ;
            List <int> pids = new List <int>();

            if (opts.PID != 0)
            {
                pids.Add(opts.PID);
            }
            if (!string.IsNullOrEmpty(opts.ProcessName))
            {
                var o = Process.GetProcessesByName(opts.ProcessName);
                pids.AddRange(o.Select(s => s.Id));
            }

            if (pids.Any())
            {
                Console.WriteLine($"Dumping {pids.Count} process ids.");
                foreach (int thisPid in pids)
                {
                    try
                    {
                        bool currProc64   = CLRUtility.Is64BitProcess();
                        bool remoteProc64 = CLRUtility.Is64BitProcess(thisPid);

                        Console.WriteLine("");
                        Console.WriteLine($"Process ID: {thisPid}");

                        if (currProc64 != remoteProc64)
                        {
                            Console.WriteLine("Process Bitness must match. This process is {0}, {1} is {2}", currProc64 ? "64-bit" : "32-bit",
                                              thisPid, remoteProc64 ? "64-bit" : "32-bit");
                            return;
                        }

                        using (DataTarget d = DataTarget.AttachToProcess(thisPid, 5000, AttachFlag.NonInvasive))
                        {
                            Console.WriteLine($"Dumping all CLRversions for process {thisPid}");
                            foreach (ClrInfo currInfo in d.ClrVersions)
                            {
                                ClrRuntime runtime = currInfo.CreateRuntime();
                                Console.WriteLine($"CLR: {currInfo.Version} GC: {(runtime.ServerGC ? "Server      " : "Workstation")} HeapSize: 0:{runtime.Heap.GetSizeByGen(0),12} 1:{runtime.Heap.GetSizeByGen(1),12} L:{runtime.Heap.GetSizeByGen(2),12}", "");
                                foreach (ClrAppDomain domain in runtime.AppDomains)
                                {
                                    IEnumerable <ClrThread> threadList = runtime.Threads.Where(x => (x.AppDomain == domain.Address));
                                    string domainInfo = $"App Domain: {domain.Name.PadRight(40)} ID: {domain.Id} Threads: {threadList.Count()} Address: {domain.Address,12:X8}";
                                    Console.WriteLine(domainInfo);

                                    Console.WriteLine($"Modules: {domain.Modules.Count.ToString("D3")} (showing GAC? {opts.GAC})");
                                    foreach (ClrModule currMod in domain.Modules)
                                    {
                                        bool printMe = (!string.IsNullOrEmpty(currMod.AssemblyName)) && (!currMod.AssemblyName.Contains("\\GAC_") | opts.GAC);
                                        if (printMe)
                                        {
                                            Console.WriteLine($"{currMod.AssemblyName}");
                                        }
                                    }

                                    if (!opts.HideThreads)
                                    {
                                        Console.WriteLine("");
                                        Console.WriteLine("Threads:");

                                        foreach (ClrThread clrt in threadList)
                                        {
                                            string threadInfo =
                                                $"  Thread: {clrt.ManagedThreadId,3:G} NT: {clrt.OSThreadId,12:X8} GC: {clrt.IsGC} {(clrt.IsAlive ? "    " : "DEAD")}";

                                            Console.WriteLine(threadInfo);
                                            int frameNum = 0;
                                            if (!opts.ShowFrames)
                                            {
                                                continue;
                                            }
                                            foreach (ClrStackFrame frame in clrt.StackTrace)
                                            {
                                                string frameInfo =
                                                    $"    Frame: {frameNum,2:G} IP: {frame.InstructionPointer,12:X} {frame.DisplayString}";
                                                Console.WriteLine(frameInfo);
                                                frameNum++;
                                            }
                                        }
                                    }


                                    if (opts.Heap)
                                    {
                                        Console.WriteLine("");
                                        Console.WriteLine("Heap Segments:");
                                        Console.WriteLine("{0,12} {1,12} {2,12} {3,12} {4,4} {5}", "Start", "End", "Committed", "Reserved", "Proc", "Type");
                                        foreach (ClrSegment thisSeg in runtime.Heap.Segments)
                                        {
                                            string type;
                                            if (thisSeg.IsEphemeral)
                                            {
                                                type = "Ephemeral";
                                            }
                                            else if (thisSeg.IsLarge)
                                            {
                                                type = "Large";
                                            }
                                            else
                                            {
                                                type = "Gen2";
                                            }

                                            Console.WriteLine("{0,12:X} {1,12:X} {2,12:X} {3,12:X} {4,4} {5}", thisSeg.Start, thisSeg.End, thisSeg.CommittedEnd, thisSeg.ReservedEnd, thisSeg.ProcessorAffinity, type);
                                        }

                                        if (opts.Recurse)
                                        {
                                            if (!runtime.Heap.CanWalkHeap)
                                            {
                                                Console.WriteLine("Can't walk heap!");
                                            }
                                            else
                                            {
                                                Console.WriteLine("Dumping LOH");
                                                foreach (ClrSegment thisSeg in runtime.Heap.Segments.Where(x => x.IsLarge))
                                                {
                                                    for (ulong objId = thisSeg.FirstObject; objId != 0; objId = thisSeg.NextObject(objId))
                                                    {
                                                        ClrType thisType = runtime.Heap.GetObjectType(objId);
                                                        ulong   thisSize = thisType.GetSize(objId);
                                                        Console.WriteLine("{0,12:X} {1,8:n0} {2,1:n0} {3}", objId, thisSize, thisSeg.GetGeneration(objId), thisType.Name);
                                                    }
                                                }
                                            }
                                        }
                                    }

                                    Console.WriteLine("");
                                }
                            }
                        }
                    }
                    catch (ArgumentException ae)
                    {
                        Console.WriteLine(ae.Message);
                    }
                    catch (ApplicationException aex)
                    {
                        Console.WriteLine(aex.Message);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                        Console.WriteLine(ex.GetType());
                        Console.WriteLine(ex.StackTrace);
                        Console.WriteLine("Cannot get the process. "
                                          + " Make sure the process exists and it's a managed process and if it's running as admin, you need to be too.");
                    }
                } //foreach (int thisPid in pids) {
            }
            else
            {
                Console.WriteLine($"No PIDS to process. Input Name: {opts.ProcessName} pid: {opts.PID}");
            };
        }