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();
        }
        internal List<UnifiedBlockingObject> GetManagedBlockingObjects(ClrThread thread, List<UnifiedStackFrame> unmanagedStack, ClrRuntime runtime)
        {
            List<UnifiedBlockingObject> result = new List<UnifiedBlockingObject>();
            if (thread.BlockingObjects?.Count > 0)
            {
                foreach (var item in thread.BlockingObjects)
                {
                    result.Add(new UnifiedBlockingObject(item));
                }
            }

            CheckForCriticalSections(result, unmanagedStack, runtime);

            foreach (var frame in unmanagedStack)
            {
                if (frame?.Handles?.Count > 0)
                {
                    foreach (var handle in frame.Handles)
                    {
                        result.Add(new UnifiedBlockingObject(handle.Id, handle.ObjectName, handle.Type));
                    }
                }
            }
            return result;
        }
 private ProcessAnalyzer(DataTarget dataTarget, ClrRuntime runtime)
 {
     _debugClient = dataTarget.DebuggerInterface;
     _dataReader = dataTarget.DataReader;
     _runtime = runtime;
     _globalConfig = Config.GetInstance();
     _isDisposed = false;
 }
 public override async Task<List<UnifiedBlockingObject>> GetUnmanagedBlockingObjects(ThreadInfo thread, List<UnifiedStackFrame> unmanagedStack, ClrRuntime runtime)
 {
     return await Task<List<UnifiedBlockingObject>>.Run(() =>
     {
         ThreadWCTInfo wct_threadInfo = _wctApi.GetBlockingObjects(thread.OSThreadId);
         return _unmanagedBlockingObjectsHandler.GetUnmanagedBlockingObjects(wct_threadInfo, unmanagedStack);
     });
 }
        internal void CheckForCriticalSections(List<UnifiedBlockingObject> list, List<UnifiedStackFrame> stack, ClrRuntime runtime)
        {
            var criticalSectionObjects = GetCriticalSectionBlockingObjects(stack, runtime);

            if (criticalSectionObjects.Any())
            {
                if (list == null)
                    list = new List<UnifiedBlockingObject>();

                list.AddRange(criticalSectionObjects);
            }
        }
Пример #6
0
        public ClrMDSession(DataTarget target, ClrRuntime runtime)
        {
            ClrMDSession.Detach();

            Target = target;
            Runtime = runtime;
            Heap = Runtime.GetHeap();

            m_allObjects = new Lazy<List<ClrObject>>(() => Heap.EnumerateClrObjects().ToList());

            s_currentSession = this;
        }
Пример #7
0
        private static bool InitApi(IntPtr ptrClient)
        {
            // On our first call to the API:
            //   1. Store a copy of IDebugClient in DebugClient.
            //   2. Replace Console's output stream to be the debugger window.
            //   3. Create an instance of DataTarget using the IDebugClient.
            if (DebugClient == null)
            {
                object client = Marshal.GetUniqueObjectForIUnknown(ptrClient);
                DebugClient = (IDebugClient)client;

                var stream = new StreamWriter(new DbgEngStream(DebugClient));
                stream.AutoFlush = true;
                Console.SetOut(stream);

                DataTarget = Microsoft.Diagnostics.Runtime.DataTarget.CreateFromDebuggerInterface(DebugClient);
            }

            // If our ClrRuntime instance is null, it means that this is our first call, or
            // that the dac wasn't loaded on any previous call.  Find the dac loaded in the
            // process (the user must use .cordll), then construct our runtime from it.
            if (Runtime == null)
            {
                // Just find a module named mscordacwks and assume it's the one the user
                // loaded into windbg.
                Process p = Process.GetCurrentProcess();
                foreach (ProcessModule module in p.Modules)
                {
                    if (module.FileName.ToLower().Contains("mscordacwks"))
                    {
                        // TODO:  This does not support side-by-side CLRs.
                        Runtime = DataTarget.ClrVersions.Single().CreateRuntime(module.FileName);
                        break;
                    }
                }

                // Otherwise, the user didn't run .cordll.
                if (Runtime == null)
                {
                    Console.WriteLine("Mscordacwks.dll not loaded into the debugger.");
                    Console.WriteLine("Run .cordll to load the dac before running this command.");
                }
            }
            else
            {
                // If we already had a runtime, flush it for this use.  This is ONLY required
                // for a live process or iDNA trace.  If you use the IDebug* apis to detect
                // that we are debugging a crash dump you may skip this call for better perf.
                Runtime.Flush();
            }

            return Runtime != null;
        }
        public virtual IEnumerable<UnifiedBlockingObject> GetCriticalSectionBlockingObjects(List<UnifiedStackFrame> unmanagedStack, ClrRuntime runtime)
        {
            foreach (var item in unmanagedStack)
            {
                UnifiedBlockingObject blockObject;

                if (_unmanagedStackWalkerStrategy.GetCriticalSectionBlockingObject(item, runtime, out blockObject))
                {
                    yield return blockObject;
                }
            }
        }
		public ClrHeapDecorator(ClrRuntime clrRuntime, ThreadDispatcher threadDispatcher)
		{
			_threadDispatcher = threadDispatcher;
			_clrHeap = threadDispatcher.Process(() => clrRuntime.GetHeap());

			

			_threadDispatcher.Process(()=>
			{
				objectIndex = IndexBuilder.Build(_clrHeap);
				GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
			});
		}
Пример #10
0
        private static IEnumerable<ThreadAndStack> GetManagedStacks(ClrRuntime runtime)
        {
            var allStacks = from thread in runtime.Threads
                            let frames = from frame in thread.StackTrace
                                         where frame.Kind == ClrStackFrameType.ManagedMethod
                                         select String.Format("{0}!{1}", frame.ModuleName, frame.Method)
                            select new ThreadAndStack
                            {
                                ManagedThreadId = thread.ManagedThreadId,
                                Stack = frames.Reverse().ToList()
                            };

            return allStacks.ToList();
        }
		private static IEnumerable<TypeHeapStat> GetHeapStatsByTypeForObjectSet(ClrRuntime clrRuntime, IEnumerable<ulong> objectIdSet)
		{
			ClrHeap heap = clrRuntime.GetHeap();

			return from oid in objectIdSet
				   let ot = heap.GetObjectType(oid)
				   group oid by ot into objectTypeGroup
				   let otSize = objectTypeGroup.Sum(oid => (uint)objectTypeGroup.Key.GetSize(oid))
				   select new TypeHeapStat
				   {
					   TypeName = objectTypeGroup.Key.Name,
					   TotalHeapSize = otSize,
					   NumberOfInstances = objectTypeGroup.Count()
				   };
		}
        internal bool GetCriticalSectionBlockingObject(UnifiedStackFrame frame, ClrRuntime runtime, out UnifiedBlockingObject blockingObject)
        {
            bool result = false;

            if (frame.Handles != null && frame.Method.Contains(ENTER_CRITICAL_SECTION_FUNCTION_NAME))
            {
                blockingObject = GetCriticalSectionBlockingObject(frame, runtime);
                result = blockingObject != null;
            }
            else
            {
                blockingObject = null;
            }

            return result;
        }
Пример #13
0
        public BlockingObjectsStrategy(
            ClrRuntime runtime, UnifiedStackTraces unifiedStackTraces = null, DataTarget dataTarget = null)
        {
            _runtime = runtime;
            _unifiedStackTraces = unifiedStackTraces;
            _dataTarget = dataTarget;

            if (_dataTarget != null)
            {
                if (_dataTarget.Architecture == Architecture.X86)
                {
                    _stackWalker = new StackWalkerStrategy_x86(_runtime);
                }

                _dataReader = _dataTarget.DataReader;
                _debugClient = _dataTarget.DebuggerInterface;
            }
        }
Пример #14
0
        public DumpAnalyzer(string dumpPath)
        {
            _target = DataTarget.LoadCrashDump(dumpPath);
            _target.SymbolLocator.SymbolPath = Environment.GetEnvironmentVariable("_NT_SYMBOL_PATH");

            if (_target.Architecture == Architecture.Amd64 && !Environment.Is64BitProcess)
            {
                throw new ApplicationException("Architecture doesn't match. Run this with X64 version.");
            }

            if (_target.ClrVersions.Count > 0)
            {
                ClrInfo dacVersion = _target.ClrVersions[0];
                _runtime = dacVersion.CreateRuntime();
                // CreateRuntime() tries to find the DAC on disk and then consults
                // the symbol server if necessary. If all fails, it throws an exception.
            }
        }
        public ProcessQuerierStrategy(IDebugClient debugClient, IDataReader dataReader, ClrRuntime runtime)
        {
            _isDispsed = false;

            _runtime = runtime;
            _dataReader = dataReader;
            _debugClient = debugClient;

            if (dataReader.GetArchitecture() == Architecture.Amd64)//Environment.Is64BitProcess
            {
                _unmanagedStackWalkerStrategy = new Unmanaged_x64_StackWalkerStrategy(_runtime);
                _threadContextStrategy = new ThreadContext_x64_Strategy();
            }
            else
            {
                _unmanagedStackWalkerStrategy = new Unmanaged_x86_StackWalkerStrategy();
                _threadContextStrategy = new ThreadContext_x86_Strategy();
            }

            _unmanagedBlockingObjectsHandler = new UnmanagedBlockingObjectsHandler(_unmanagedStackWalkerStrategy);
        }
        internal List<UnifiedStackFrame> ConvertToUnified(IEnumerable<DEBUG_STACK_FRAME> stackFrames,
            ClrRuntime runtime, IDebugClient debugClient, ThreadInfo info, uint pid = Constants.INVALID_PID)
        {
            bool waitFound = false;
            var reversed = stackFrames.Reverse();
            List<UnifiedStackFrame> stackTrace = new List<UnifiedStackFrame>();

            foreach (var frame in reversed)
            {
                var unified_frame = new UnifiedStackFrame(frame, (IDebugSymbols2)debugClient);
                unified_frame.ThreadContext = info.ContextStruct;

                if (!waitFound)
                {
                    waitFound = Inpsect(unified_frame, runtime, pid);
                }

                stackTrace.Add(unified_frame);
            }

            return stackTrace;
        }
Пример #17
0
        private void TouchOtherRegions(DumpReaderLogger readerLogger, ClrRuntime runtime)
        {
            // Touch all threads, stacks, frames
            foreach (var t in runtime.Threads)
            {
                foreach (var f in t.StackTrace)
                {
                    try { f.GetFileAndLineNumber(); }
                    catch (Exception) { }
                }
            }

            // Touch all modules
            runtime.EnumerateModules().Count();

            // Touch all heap regions, roots, types
            var heap = runtime.GetHeap();
            heap.EnumerateRoots(enumerateStatics: false).Count();
            heap.EnumerateTypes().Count();

            // TODO Check if it's faster to construct sorted inside ReaderWrapper
            foreach (var kvp in readerLogger.Ranges)
                _otherClrRegions.Add(kvp.Key, kvp.Value);
        }
        internal List<UnifiedBlockingObject> GetUnmanagedBlockingObjects(ThreadInfo thread, List<UnifiedStackFrame> unmanagedStack, ClrRuntime runtime, List<MiniDumpHandle> DumpHandles)
        {
            List<UnifiedBlockingObject> result = new List<UnifiedBlockingObject>();

            result.AddRange(GetUnmanagedBlockingObjects(unmanagedStack));

            foreach (var item in DumpHandles)
            {
                result.Add(new UnifiedBlockingObject(item));
            }

            CheckForCriticalSections(result, unmanagedStack, runtime);

            return result;
        }
 public virtual List<UnifiedBlockingObject> GetManagedBlockingObjects(ClrThread thread, List<UnifiedStackFrame> unmanagedStack, ClrRuntime runtime)
 {
     return _unmanagedBlockingObjectsHandler.GetManagedBlockingObjects(thread, unmanagedStack, runtime);
 }
 public virtual IEnumerable<UnifiedBlockingObject> GetCriticalSectionBlockingObjects(List<UnifiedStackFrame> unmanagedStack, ClrRuntime runtime)
 {
     return _unmanagedBlockingObjectsHandler.GetCriticalSectionBlockingObjects(unmanagedStack, runtime);
 }
 public List<UnifiedStackFrame> ConvertToUnified(IEnumerable<DEBUG_STACK_FRAME> stackFrames, ClrRuntime runtime, ThreadInfo info, uint pID)
 {
     var result = _unmanagedStackWalkerStrategy.ConvertToUnified(stackFrames, runtime, _debugClient, info, pID);
     return result;
 }
 public abstract Task<List<UnifiedBlockingObject>> GetUnmanagedBlockingObjects(ThreadInfo thread, List<UnifiedStackFrame> unmanagedStack, ClrRuntime runtime);
        /// <summary>
        /// Original Function call example: 
        ///     void WINAPI EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
        /// </summary>
        protected override UnifiedBlockingObject GetCriticalSectionBlockingObject(UnifiedStackFrame frame, ClrRuntime runtime)
        {
            UnifiedBlockingObject result = null;

            var paramz = Strategy.GetEnterCriticalSectionParam(frame);
            result = new UnifiedBlockingObject(paramz.First, UnifiedBlockingType.CriticalSectionObject);

            return result;
        }
 /// <summary>
 ///  Original Function call example: 
 ///    DWORD WINAPI WaitForSingleObject(HANDLE hHandle,DWORD  dwMilliseconds);
 /// </summary>
 protected override void DealWithSingle(UnifiedStackFrame frame, ClrRuntime runtime, uint pid)
 {
     var paramz = Strategy.GetWaitForSingleObjectParams(frame);
     EnrichUnifiedStackFrame(frame, paramz.First, pid);
 }
 /// <summary>
 /// Original Function call example: 
 ///     DWORD WaitForMultipleObjects(DWORD  nCount,HANDLE* lpHandles,BOOL bWaitAll,DWORD dwMilliseconds);
 /// </summary>
 protected override void DealWithMultiple(UnifiedStackFrame frame, ClrRuntime runtime, uint pid)
 {
     var paramz = Strategy.GetWaitForMultipleObjectsParams(frame);
     EnrichUnifiedStackFrame(frame, runtime, pid, paramz.First, paramz.Second);
 }
 /// <summary>
 /// Original Function call example: 
 ///     void WINAPI EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
 /// </summary>
 protected override void DealWithCriticalSection(UnifiedStackFrame frame, ClrRuntime runtime, uint pid)
 {
     var paramz = Strategy.GetEnterCriticalSectionParam(frame);
     EnrichUnifiedStackFrame(frame, paramz.First, pid);
 }
 public Unmanaged_x64_StackWalkerStrategy(ClrRuntime runtime)
 {
     _globalConfigs = Config.GetInstance();
     _runtime = runtime;
 }
Пример #28
0
        /// <summary>
        /// See https://github.com/goldshtn/msos/commit/705d3758d15835d2520b31fcf3028353bdbca73b#commitcomment-12499813
        /// and https://github.com/Microsoft/dotnetsamples/blob/master/Microsoft.Diagnostics.Runtime/CLRMD/ClrMemDiag/Debugger/IDebugControl.cs#L126-L156
        /// </summary>
        private void PrintAssemblyCode(ClrMethod method, IList<ILToNativeMap> ilMaps, ClrRuntime runtime, IDebugControl debugControl)
        {
            // This is the first instruction of the JIT'ed (or NGEN'ed) machine code.
            ulong startAddress = ilMaps.Select(entry => entry.StartAddress).Min();

            // Unfortunately there's not a great way to get the size of the code, or the end address.
            // You are supposed to do code flow analysis like "uf" in windbg to find the size, but
            // in practice you can use the IL to native mapping:
            ulong endAddress = ilMaps.Select(entry => entry.EndAddress).Max();

            var bufferSize = 500; // per-line
            var lineOfAssembly = new StringBuilder(bufferSize);
            ulong startOffset = startAddress, endOffset;
            uint disassemblySize;
            do
            {
                var flags = DEBUG_DISASM.EFFECTIVE_ADDRESS;
                var result = debugControl.Disassemble(startOffset, flags, lineOfAssembly, bufferSize, out disassemblySize, out endOffset);
                startOffset = endOffset;
                logger?.Write(lineOfAssembly.ToString());

                if (lineOfAssembly.ToString().Contains(" call ") == false)
                    continue;

                var methodCallInfo = GetCalledMethodFromAssemblyOutput(runtime, lineOfAssembly.ToString());
                if (string.IsNullOrWhiteSpace(methodCallInfo) == false)
                    logger?.WriteLine(LogKind.Info, $"  {methodCallInfo}");
            } while (disassemblySize > 0 && endOffset <= endAddress);
            logger?.WriteLine();
        }
Пример #29
0
        private string GetCalledMethodFromAssemblyOutput(ClrRuntime runtime, string assemblyString)
        {
            string hexAddressText = "";
            var callLocation = assemblyString.LastIndexOf("call");
            var qwordPtrLocation = assemblyString.IndexOf("qword ptr");
            var openBracket = assemblyString.IndexOf('(');
            var closeBracket = assemblyString.IndexOf(')');

            if (openBracket != -1 && closeBracket != -1 && closeBracket > openBracket)
            {
                // 000007fe`979171fb e800261b5e      call    mscorlib_ni+0x499800 (000007fe`f5ac9800)
                hexAddressText = assemblyString.Substring(openBracket, closeBracket - openBracket)
                                               .Replace("(", "")
                                               .Replace(")", "")
                                               .Replace("`", "");
            }
            else if (callLocation != -1 && qwordPtrLocation != -1)
            {
                // TODO have to also deal with:
                // 000007fe`979f666f 41ff13          call    qword ptr [r11] ds:000007fe`978e0050=000007fe978ed260
            }
            else if (callLocation != -1)
            {
                // 000007fe`979e6721 e8e2b5ffff      call    000007fe`979e1d08
                var endOfCallLocation = callLocation + 4;
                hexAddressText = assemblyString.Substring(endOfCallLocation, assemblyString.Length - endOfCallLocation)
                                               .Replace("`", "")
                                               .Trim(' ');
            }

            ulong actualAddress;
            if (ulong.TryParse(hexAddressText, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out actualAddress))
            {
                ClrMethod method = runtime.GetMethodByAddress(actualAddress);
                if (method != null)
                {
                    return $"Call: {method.GetFullSignature()}";
                }
                else
                    return $"Call: {actualAddress:x16} -> No matching method found";
            }

            return $"\"{hexAddressText}\" -> Not a valid hex value";
        }
Пример #30
0
        private void PrintRuntimeDiagnosticInfo(DataTarget dataTarget, ClrRuntime runtime)
        {
            logger?.WriteLine(LogKind.Header, "\nRuntime Diagnostic Information");
            logger?.WriteLine(LogKind.Header, "------------------------------");

            logger?.WriteLine(LogKind.Header, "\nDataTarget Info:");
            logger?.WriteLine(LogKind.Info, "  ClrVersion{0}: {1}", dataTarget.ClrVersions.Count > 1 ? "s" : "", string.Join(", ", dataTarget.ClrVersions));
            logger?.WriteLine(LogKind.Info, "  Architecture: " + dataTarget.Architecture);
            logger?.WriteLine(LogKind.Info, "  PointerSize: {0} ({1}-bit)", dataTarget.PointerSize, dataTarget.PointerSize == 8 ? 64 : 32);
            logger?.WriteLine(LogKind.Info, "  SymbolPath: " + dataTarget.GetSymbolPath());

            logger?.WriteLine(LogKind.Header, "\nClrRuntime Info:");
            logger?.WriteLine(LogKind.Info, "  ServerGC: " + runtime.ServerGC);
            logger?.WriteLine(LogKind.Info, "  HeapCount: " + runtime.HeapCount);
            logger?.WriteLine(LogKind.Info, "  Thread Count: " + runtime.Threads.Count);

            logger?.WriteLine(LogKind.Header, "\nClrRuntime Modules:");
            foreach (var module in runtime.EnumerateModules())
            {
                logger?.WriteLine(LogKind.Info,
                                  "  {0,36} Id:{1} - {2,10:N0} bytes @ 0x{3:X16}",
                                  Path.GetFileName(module.FileName),
                                  module.AssemblyId.ToString().PadRight(10),
                                  module.Size,
                                  module.ImageBase);
            }

            ClrHeap heap = runtime.GetHeap();
            logger?.WriteLine(LogKind.Header, "\nClrHeap Info:");
            logger?.WriteLine(LogKind.Info, "  TotalHeapSize: {0:N0} bytes ({1:N2} MB)", heap.TotalHeapSize, heap.TotalHeapSize / 1024.0 / 1024.0);
            logger?.WriteLine(LogKind.Info, "  Gen0: {0,10:N0} bytes", heap.GetSizeByGen(0));
            logger?.WriteLine(LogKind.Info, "  Gen1: {0,10:N0} bytes", heap.GetSizeByGen(1));
            logger?.WriteLine(LogKind.Info, "  Gen2: {0,10:N0} bytes", heap.GetSizeByGen(2));
            logger?.WriteLine(LogKind.Info, "   LOH: {0,10:N0} bytes", heap.GetSizeByGen(3));

            logger?.WriteLine(LogKind.Info, "  Segments: " + heap.Segments.Count);
            foreach (var segment in heap.Segments)
            {
                logger?.WriteLine(LogKind.Info,
                                  "    Segment: {0,10:N0} bytes, {1,10}, Gen0: {2,10:N0} bytes, Gen1: {3,10:N0} bytes, Gen2: {4,10:N0} bytes",
                                  segment.Length,
                                  segment.IsLarge ? "Large" : (segment.IsEphemeral ? "Ephemeral" : "Unknown"),
                                  segment.Gen0Length,
                                  segment.Gen1Length,
                                  segment.Gen2Length);
            }

            logger?.WriteLine();
        }