Example #1
0
        private void LoadFile(string name)
        {
            var path = Path.Combine(TestsHelper.GetTestFilesLocation(), name);

            var text = File.ReadAllText(path);

            var tree = CSharpSyntaxTree.ParseText(text);

            _compilation = CSharpCompilation.Create("TestCompilation", new[] { tree });
            _sut         = new ReferencesWalker(_compilation, new Func <string, bool>[] {});
        }
Example #2
0
        private static void Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.WriteLine("@ Dump2SQLite - Serialize GCHeap to SQLite DB @");
                Console.WriteLine(@"Usage: Dump2SQLite \path\to\filename.dmp");
                Console.WriteLine(@"Output: SQLite DB (\path\to\filename.sqlite)");
                return;
            }

            string dumpLocation = args[0];

            Stopwatch watch = new Stopwatch();
            watch.Start();

            LogInfoWithTimeStamp("Loading Crash Dump from: " + dumpLocation + " ...");

            DataTarget target = DataTarget.LoadCrashDump(dumpLocation);
            ClrInfo version = target.ClrVersions[0]; // TODO: Probably add support for Multiple CLRs or at least warn we're picking the first
            string dacLocation = version.TryGetDacLocation();
            ClrRuntime runtime = target.CreateRuntime(dacLocation);

            var heap = runtime.GetHeap();
            if (!heap.CanWalkHeap)
            {
                LogErrorWithTimeStamp("Heap is not walkable. Please collect a new dump.");
                return;
            }

            LogInfoWithTimeStamp("Crash Dump loaded.");

            var perTypeCounts = new Dictionary<int, int>(100000);

            var fileName = Path.GetFullPath(args[0]).Replace(Path.GetExtension(args[0]), ".sqlite");

            LogInfoWithTimeStamp("Creating SQLite Database filename: " + fileName + " ...");

            sqlite3* db;
            int error;
            if ((error = NativeMethods.sqlite3_open(fileName, out db)) != 0)
            {
                LogErrorWithTimeStamp("sqlite3_open failed with error code: " + error);
            }

            LogInfoWithTimeStamp("Successfully created SQLite Database filename: " + fileName);

            LogInfoWithTimeStamp("Creating SQLite Tables ...");

            if (!CreateTables(db))
            {
                return;
            }

            LogInfoWithTimeStamp("Successfully created SQLite Tables.");

            error = NativeMethods.sqlite3_exec(db, "BEGIN TRANSACTION;", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
            if (error != 0)
            {
                LogErrorWithTimeStamp("sqlite3_exec -> BEGIN TRANSACTION; failed to execute with SQLite error code: " + error);
            }

            sqlite3_stmt* insertObjectsStmt,
                insertTypesStmt,
                insertRootsStmt,
                insertBlockingObjectsStmt,
                insertExceptionsStmt,
                insertThreadsStmt;

            if (!PrepareInsertStatement(db, out insertTypesStmt, @"INSERT INTO Types(TypeIndex, Count, Size, Name) VALUES (@1, @2, @3, @4);"))
            {
                return;
            }

            if (!PrepareInsertStatement(db, out insertObjectsStmt, @"INSERT INTO Objects(ObjectId, TypeIndex, Size, ObjRefs) VALUES (@1, @2, @3, @4);"))
            {
                return;
            }

            if (!PrepareInsertStatement(db, out insertRootsStmt, @"INSERT INTO Roots(TypeIndex, ObjectId, Address, AppDomainId, ManagedThreadId, IsInterior, IsPinned, IsPossibleFalsePositive, GCRootKind, Name) VALUES (@1, @2, @3, @4, @5, @6, @7, @8, @9, @10);"))
            {
                return;
            }

            if (!PrepareInsertStatement(db, out insertBlockingObjectsStmt, @"INSERT INTO BlockingObjects(ObjectId, Taken, RecursionCount, Owner, HasSingleOwner, ThreadOwnerIds, ThreadWaiterIds, BlockingReason) VALUES (@1, @2, @3, @4, @5, @6, @7, @8);"))
            {
                return;
            }

            /*
            if (!PrepareInsertStatement(db, out insertExceptionsStmt, @"INSERT INTO Exceptions(ExceptionId, TypeId, Type, Message, Address, InnerExceptionId, HResult, StackId, StackTrace) VALUES (@1, @2, @3, @4, @5, @6, @7, @8, @9);"))
            {
                return;
            }*/

            /*
            if (!PrepareInsertStatement(db, out insertThreadsStmt, @"(GcMode, IsFinalizer, Address, IsAlive, OSThreadId, ManagedThreadId, AppDomain, LockCount, Teb, StackBase, StackLimit, StackId, ExceptionId, IsGC, IsDebuggerHelper, IsThreadpoolTimer, IsThreadpoolCompletionPort, IsThreadpoolWorker, IsThreadpoolWait, IsThreadpoolGate, IsSuspendingEE, IsShutdownHelper, IsAbortRequested, IsAborted, ISGCSuspendPending, IsDebugSuspended, IsBackground, IsUnstarted, IsCoInitialized, IsSTA, IsMTA, BlockingObjects, Roots) VALUES (@1, @2, @3, @4, @5, @6, @7, @8, @9, @10);"))
            {
                return;
            }*/

            LogInfoWithTimeStamp("Starting to populate Objects Table ...");

            var walker = new ReferencesWalker();
            foreach (ulong obj in heap.EnumerateObjects())
            {
                ClrType type = heap.GetObjectType(obj);
                if (type != null)
                {
                    type.EnumerateRefsOfObjectCarefully(obj, walker.Walk);
                    var references = walker.ToString();
                    walker.Clear();

                    int typeIndex = type.Index;
                    if (perTypeCounts.ContainsKey(typeIndex))
                    {
                        ++perTypeCounts[typeIndex];
                    }
                    else
                    {
                        perTypeCounts.Add(typeIndex, 1);
                    }

                    NativeMethods.sqlite3_bind_int64(insertObjectsStmt, 1, (long)obj);
                    NativeMethods.sqlite3_bind_int(insertObjectsStmt, 2, typeIndex);
                    NativeMethods.sqlite3_bind_int(insertObjectsStmt, 3, type.BaseSize);
                    NativeMethods.sqlite3_bind_text(insertObjectsStmt, 4, references, references.Length, NativeMethods.Transient);

                    NativeMethods.sqlite3_step(insertObjectsStmt);
                    NativeMethods.sqlite3_reset(insertObjectsStmt);
                }
            }

            LogInfoWithTimeStamp("Successfully populated Objects Table.");
            LogInfoWithTimeStamp("Starting to populate Types Table ...");

            foreach (var type in heap.EnumerateTypes())
            {
                string typeName = type.Name;
                int typeIndex = type.Index;
                int count;
                if (!perTypeCounts.TryGetValue(typeIndex, out count))
                {
                    count = 0;
                }

                NativeMethods.sqlite3_bind_int(insertTypesStmt, 1, typeIndex);
                NativeMethods.sqlite3_bind_int64(insertTypesStmt, 2, count);
                NativeMethods.sqlite3_bind_int(insertTypesStmt, 3, type.BaseSize);
                NativeMethods.sqlite3_bind_text(insertTypesStmt, 4, typeName, typeName.Length, NativeMethods.Transient);

                NativeMethods.sqlite3_step(insertTypesStmt);
                NativeMethods.sqlite3_reset(insertTypesStmt);
            }

            LogInfoWithTimeStamp("Successfully populated Types Table.");
            LogInfoWithTimeStamp("Starting to populate Roots Table ...");

            foreach (var root in heap.EnumerateRoots())
            {
                NativeMethods.sqlite3_bind_int(insertRootsStmt, 1, root.Type?.Index ?? -1);
                NativeMethods.sqlite3_bind_int64(insertRootsStmt, 2, (long)root.Object);
                NativeMethods.sqlite3_bind_int64(insertRootsStmt, 3, (long)root.Address);
                NativeMethods.sqlite3_bind_int(insertRootsStmt, 4, root.AppDomain?.Id ?? -1);
                NativeMethods.sqlite3_bind_int(insertRootsStmt, 5, root.Thread?.ManagedThreadId ?? -1);
                NativeMethods.sqlite3_bind_int(insertRootsStmt, 6, root.IsInterior ? 1 : 0);
                NativeMethods.sqlite3_bind_int(insertRootsStmt, 7, root.IsPinned ? 1 : 0);
                NativeMethods.sqlite3_bind_int(insertRootsStmt, 8, root.IsPossibleFalsePositive ? 1 : 0);

                string kindString = root.Kind.KindString();
                string rootName = root.Name;

                NativeMethods.sqlite3_bind_text(insertRootsStmt, 9, kindString, kindString.Length, NativeMethods.Transient);
                NativeMethods.sqlite3_bind_text(insertRootsStmt, 10, rootName, rootName.Length, NativeMethods.Transient);

                NativeMethods.sqlite3_step(insertRootsStmt);
                NativeMethods.sqlite3_reset(insertRootsStmt);
            }

            LogInfoWithTimeStamp("Successfully populated Roots Table.");
            LogInfoWithTimeStamp("Starting to populate Blocking Objects Table ...");

            foreach (var blockingObject in heap.EnumerateBlockingObjects())
            {
                NativeMethods.sqlite3_bind_int64(insertBlockingObjectsStmt, 1, (long)blockingObject.Object);
                NativeMethods.sqlite3_bind_int64(insertBlockingObjectsStmt, 2, blockingObject.Taken ? 1 : 0);
                NativeMethods.sqlite3_bind_int64(insertBlockingObjectsStmt, 3, blockingObject.RecursionCount);
                NativeMethods.sqlite3_bind_int64(insertBlockingObjectsStmt, 4, blockingObject.Owner?.ManagedThreadId ?? -1);
                NativeMethods.sqlite3_bind_int(insertBlockingObjectsStmt, 5, blockingObject.HasSingleOwner ? 1 : 0);

                var owners = blockingObject.Owners.Expand();
                NativeMethods.sqlite3_bind_text(insertBlockingObjectsStmt, 6, owners, owners.Length, NativeMethods.Transient);

                var waiters = blockingObject.Waiters.Expand();
                NativeMethods.sqlite3_bind_text(insertBlockingObjectsStmt, 7, waiters, waiters.Length, NativeMethods.Transient);

                var blockingReason = blockingObject.Reason.KindString();
                NativeMethods.sqlite3_bind_text(insertBlockingObjectsStmt, 8, blockingReason, blockingReason.Length, NativeMethods.Transient);

                NativeMethods.sqlite3_step(insertBlockingObjectsStmt);
                NativeMethods.sqlite3_reset(insertBlockingObjectsStmt);
            }

            LogInfoWithTimeStamp("Successfully populated Blocking Objects Table.");

            NativeMethods.sqlite3_finalize(insertTypesStmt);
            NativeMethods.sqlite3_finalize(insertObjectsStmt);
            NativeMethods.sqlite3_finalize(insertRootsStmt);
            NativeMethods.sqlite3_finalize(insertBlockingObjectsStmt);

            error = NativeMethods.sqlite3_exec(db, "END TRANSACTION;", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
            if (error != 0)
            {
                LogErrorWithTimeStamp("sqlite3_exec -> END TRANSACTION; failed to execute with SQLite error code: " + error);
            }

            NativeMethods.sqlite3_close(db);

            watch.Stop();
            LogInfoWithTimeStamp("Processing time: " + watch.ElapsedMilliseconds + "  milliseconds");
        }