public static ClrObject GetStaticObjectValue(this ClrType mainType, string fieldName) { ClrStaticField field = mainType.GetStaticFieldByName(fieldName); ulong obj = (ulong)field.GetValue(field.Type.Heap.Runtime.AppDomains.Single()); return(new ClrObject(obj, mainType.Heap.GetObjectType(obj))); }
public static ClrObject GetStaticFldValue(this ClrRuntime runtime, [NotNull] ClrType clrType, [NotNull] string fieldName) { Assert.ArgumentNotNull(clrType, "typeName"); Assert.ArgumentNotNullOrEmpty(fieldName, "fieldName"); ClrStaticField fld = clrType.GetStaticFieldByName(fieldName); if (fld == null) { throw new MissingFieldException(clrType.Name, fieldName); } var domains = runtime.AppDomains.ToArray(); if ((domains == null) || (domains.Length == 0)) { throw new ArgumentException("No domains are found inside runtime!"); } ulong?resultAddress = (from domain in domains where !string.IsNullOrWhiteSpace(domain.Name) where !domain.Name.Contains("Default") && fld.IsInitialized(domain) select(ulong?) fld.GetValue(domain)).FirstOrDefault(); return(resultAddress.HasValue ? (new ClrObject(resultAddress.Value, clrType.Heap)) : ClrObject.NullObject); }
public dynamic GetValue(ClrAppDomain appDomain) { if (m_field.IsPrimitive()) { object value = m_field.GetValue(appDomain); if (value != null) { return(new ClrPrimitiveValue(value, m_field.ElementType)); } } else if (m_field.IsValueClass()) { ulong addr = m_field.GetAddress(appDomain); if (addr != 0) { return(new ClrObject(m_heap, m_field.Type, addr, true)); } } else if (m_field.ElementType == ClrElementType.String) { ulong addr = m_field.GetAddress(appDomain); if (m_heap.GetRuntime().ReadPointer(addr, out addr)) { return(new ClrObject(m_heap, m_field.Type, addr)); } } else { object value = m_field.GetValue(appDomain); if (value != null) { return(new ClrObject(m_heap, m_field.Type, (ulong)value)); } } return(new ClrNullValue(m_heap)); }
public void IntegerObjectClrType() { using (DataTarget dt = TestTargets.Types.LoadFullDump()) { ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); ClrHeap heap = runtime.Heap; ClrStaticField field = runtime.GetModule("types.exe").GetTypeByName("Types").GetStaticFieldByName("s_i"); ulong addr = (ulong)field.GetValue(runtime.AppDomains.Single()); ClrType type = heap.GetObjectType(addr); Assert.True(type.IsPrimitive); Assert.False(type.IsObjectReference); Assert.False(type.IsValueClass); object value = type.GetValue(addr); Assert.Equal("42", value.ToString()); Assert.IsType <int>(value); Assert.Equal(42, (int)value); Assert.Contains(addr, heap.EnumerateObjectAddresses()); } }
public IEnumerable <ObjectInfo> EnumerateManagedWorkItems() { ClrStaticField workQueueField = ClrMdUtils.GetCorlib(runtime).GetTypeByName("System.Threading.ThreadPoolGlobals")?.GetStaticFieldByName("workQueue"); if (workQueueField != null) { object workQueueValue = workQueueField.GetValue(domain); ulong workQueueRef = (workQueueValue == null) ? 0L : (ulong)workQueueValue; if (workQueueRef != 0) { ClrType workQueueType = heap.GetObjectType(workQueueRef); // should be System.Threading.ThreadPoolWorkQueue if (workQueueType?.Name == "System.Threading.ThreadPoolWorkQueue") { foreach (var item in EnumerateThreadPoolWorkQueue(workQueueRef)) { yield return(new ObjectInfo { Address = item, Type = heap.GetObjectType(item) }); } } } } }
public override IEnumerable <ObjectInfo> EnumerateTimerTasks() { if (fieldSQueue.IsInitialized(domain)) { var timeQueue = (ulong)fieldSQueue.GetValue(domain); for (ulong timer = (ulong)fieldTimers.GetValue(timeQueue); timer != 0; timer = (ulong)fieldNext.GetValue(timer)) { var state = (ulong)fieldState.GetValue(timer); if (state != 0) { var typeState = heap.GetObjectType(state); if (typeState == typeDelayPromise) { var continuation = (ulong)fieldTaskContinuationObject.GetValue(state); var target = (ulong)fieldDelegateTarget.GetValue(continuation); var stateMachine = (ulong)fieldStateMachine.GetValue(target); yield return(new ObjectInfo { Address = stateMachine, Type = heap.GetObjectType(stateMachine) }); } } } } }
public void RunDone() { _workItems = new Dictionary <string, WorkInfo>(); _workItemCount = 0; _tasks = new Dictionary <string, WorkInfo>(); _taskCount = 0; ClrMDHelper helper = new ClrMDHelper(_host.Session.Clr); // The ThreadPool is keeping track of the pending work items into two different areas: // - a global queue: stored by ThreadPoolWorkQueue instances of the ThreadPoolGlobals.workQueue static field // - several per thread (TLS) local queues: stored in SparseArray<ThreadPoolWorkQueue+WorkStealingQueue> linked from ThreadPoolWorkQueue.allThreadQueues static fields // both are using arrays of Task or QueueUserWorkItemCallback // // NOTE: don't show other thread pool related topics such as timer callbacks or wait objects // try { var heap = _host.Session.Clr.Heap; var clr = _host.Session.Clr; _host.WriteLine("global work item queue________________________________"); // look for the ThreadPoolGlobals.workQueue static field ClrModule mscorlib = helper.GetMscorlib(); if (mscorlib == null) { return; } ClrType queueType = mscorlib.GetTypeByName("System.Threading.ThreadPoolGlobals"); if (queueType == null) { return; } ClrStaticField workQueueField = queueType.GetStaticFieldByName("workQueue"); if (workQueueField == null) { return; } // the CLR keeps one static instance per application domain foreach (var appDomain in clr.AppDomains) { object workQueueValue = workQueueField.GetValue(appDomain); ulong workQueueRef = (workQueueValue == null) ? 0L : (ulong)workQueueValue; if (workQueueRef == 0) { continue; } // should be System.Threading.ThreadPoolWorkQueue ClrType workQueueType = heap.GetObjectType(workQueueRef); if (workQueueType == null) { continue; } if (workQueueType.Name != "System.Threading.ThreadPoolWorkQueue") { continue; } if (!DumpThreadPoolWorkQueue(workQueueType, workQueueRef)) { _host.WriteLine("Impossible to dump thread pool work queue @ 0x" + workQueueRef.ToString("X")); } } // look into the local stealing queues in each thread TLS // hopefully, they are all stored in static (one per app domain) instance // of ThreadPoolWorkQueue.SparseArray<ThreadPoolWorkQueue.WorkStealingQueue> // _host.WriteLine("\r\nlocal per thread work items_____________________________________"); try { queueType = mscorlib.GetTypeByName("System.Threading.ThreadPoolWorkQueue"); if (queueType == null) { return; } ClrStaticField threadQueuesField = queueType.GetStaticFieldByName("allThreadQueues"); if (threadQueuesField == null) { return; } foreach (ClrAppDomain domain in clr.AppDomains) { ulong?threadQueue = (ulong?)threadQueuesField.GetValue(domain); if (!threadQueue.HasValue || threadQueue.Value == 0) { continue; } ClrType threadQueueType = heap.GetObjectType(threadQueue.Value); if (threadQueueType == null) { continue; } var sparseArrayRef = _host.Session.GetFieldValue(threadQueue.Value, "m_array"); _host.Session.ForEach((ulong)sparseArrayRef, stealingQueue => { if (stealingQueue != 0) { var arrayRef = _host.Session.GetFieldValue(stealingQueue, "m_array"); DumpThreadPoolWorkItems((ulong)arrayRef); } }); } } finally { // provide a summary sorted by count // tasks first if any if (_tasks.Values.Count > 0) { foreach (var item in _tasks.Values.OrderBy(wi => wi.Count)) { _host.WriteLine(string.Format(" {0,4} Task {1}", item.Count.ToString(), item.Name)); } _host.WriteLine(" ----"); _host.WriteLine(string.Format(" {0,4}\r\n", _taskCount.ToString())); } // then QueueUserWorkItem next if any if (_workItems.Values.Count > 0) { foreach (var item in _workItems.Values.OrderBy(wi => wi.Count)) { _host.WriteLine(string.Format(" {0,4} Work {1}", item.Count.ToString(), item.Name)); } _host.WriteLine(" ----"); _host.WriteLine(string.Format(" {0,4}\r\n", _workItemCount.ToString())); } var threadPool = _host.Session.Clr.ThreadPool; _host.WriteLine(string.Format( "\r\nCPU = {0}% for {1} threads (#idle = {2} + #running = {3} | #dead = {4} | #max = {5})", threadPool.CpuUtilization.ToString(), threadPool.TotalThreads.ToString(), threadPool.IdleThreads.ToString(), threadPool.RunningThreads.ToString(), _host.Session.Clr.Threads.Count(t => t.IsThreadpoolWorker && !t.IsThreadpoolCompletionPort && !t.IsAlive && !t.IsThreadpoolGate && !t.IsThreadpoolTimer && !t.IsThreadpoolWait).ToString(), threadPool.MaxThreads.ToString() )); // show the running worker threads DumpRunningThreadpoolThreads(helper); } } catch (Exception x) { _host.WriteLine(x.Message); } }
/// <summary> /// Gets the value of the static field. /// </summary> /// <param name="appDomain">The AppDomain in which to get the value.</param> /// <returns>The value of this static field.</returns> /// <inheritdoc /> public object GetValue(IClrAppDomain appDomain) => StaticField.GetValue((appDomain as ClrAppDomainAdapter)?.AppDomain);
private static IEnumerable <TimerInfo> EnumerateTimers(ClrRuntime clr) { var timerQueueType = Utils.GetMscorlib(clr).GetTypeByName("System.Threading.TimerQueue"); if (timerQueueType == null) { yield break; } ClrStaticField instanceField = timerQueueType.GetStaticFieldByName("s_queue"); if (instanceField == null) { yield break; } var heap = clr.Heap; foreach (ClrAppDomain domain in clr.AppDomains) { ulong?timerQueue = (ulong?)instanceField.GetValue(domain); if (!timerQueue.HasValue || timerQueue.Value == 0) { continue; } ClrType t = heap.GetObjectType(timerQueue.Value); if (t == null) { continue; } // m_timers is the start of the list of TimerQueueTimer var currentPointer = Utils.GetFieldValue(heap, timerQueue.Value, "m_timers"); while ((currentPointer != null) && (((ulong)currentPointer) != 0)) { // currentPointer points to a TimerQueueTimer instance ulong currentTimerQueueTimerRef = (ulong)currentPointer; TimerInfo ti = new TimerInfo() { TimerQueueTimerAddress = currentTimerQueueTimerRef }; var val = Utils.GetFieldValue(heap, currentTimerQueueTimerRef, "m_dueTime"); ti.DueTime = (uint)val; val = Utils.GetFieldValue(heap, currentTimerQueueTimerRef, "m_period"); ti.Period = (uint)val; val = Utils.GetFieldValue(heap, currentTimerQueueTimerRef, "m_canceled"); ti.Cancelled = (bool)val; val = Utils.GetFieldValue(heap, currentTimerQueueTimerRef, "m_state"); ti.StateTypeName = ""; if (val == null) { ti.StateAddress = 0; } else { ti.StateAddress = (ulong)val; var stateType = heap.GetObjectType(ti.StateAddress); if (stateType != null) { ti.StateTypeName = stateType.Name; } } // decypher the callback details val = Utils.GetFieldValue(heap, currentTimerQueueTimerRef, "m_timerCallback"); if (val != null) { ulong elementAddress = (ulong)val; if (elementAddress == 0) { continue; } var elementType = heap.GetObjectType(elementAddress); if (elementType != null) { if (elementType.Name == "System.Threading.TimerCallback") { ti.MethodName = Utils.BuildTimerCallbackMethodName(clr, heap, elementAddress); } else { ti.MethodName = "<" + elementType.Name + ">"; } } else { ti.MethodName = "{no callback type?}"; } } else { ti.MethodName = "???"; } yield return(ti); currentPointer = Utils.GetFieldValue(heap, currentTimerQueueTimerRef, "m_next"); } } }
private IEnumerable <ulong> EnumerateManagedThreadpoolObjects() { _heap = _runtime.GetHeap(); ClrModule mscorlib = GetMscorlib(); if (mscorlib != null) { ClrType queueType = mscorlib.GetTypeByName("System.Threading.ThreadPoolGlobals"); if (queueType != null) { ClrStaticField workQueueField = queueType.GetStaticFieldByName("workQueue"); if (workQueueField != null) { foreach (var appDomain in _runtime.AppDomains) { object workQueueValue = workQueueField.GetValue(appDomain); ulong workQueue = workQueueValue == null ? 0L : (ulong)workQueueValue; ClrType workQueueType = _heap.GetObjectType(workQueue); if (workQueue == 0 || workQueueType == null) { continue; } ulong queueHead; ClrType queueHeadType; do { if (!GetFieldObject(workQueueType, workQueue, "queueHead", out queueHeadType, out queueHead)) { break; } ulong nodes; ClrType nodesType; if (GetFieldObject(queueHeadType, queueHead, "nodes", out nodesType, out nodes) && nodesType.IsArray) { int len = nodesType.GetArrayLength(nodes); for (int i = 0; i < len; ++i) { ulong addr = (ulong)nodesType.GetArrayElementValue(nodes, i); if (addr != 0) { yield return(addr); } } } if (!GetFieldObject(queueHeadType, queueHead, "Next", out queueHeadType, out queueHead)) { break; } } while (queueHead != 0); } } } queueType = mscorlib.GetTypeByName("System.Threading.ThreadPoolWorkQueue"); if (queueType != null) { ClrStaticField threadQueuesField = queueType.GetStaticFieldByName("allThreadQueues"); if (threadQueuesField != null) { foreach (ClrAppDomain domain in _runtime.AppDomains) { ulong?threadQueue = (ulong?)threadQueuesField.GetValue(domain); if (!threadQueue.HasValue || threadQueue.Value == 0) { continue; } ClrType threadQueueType = _heap.GetObjectType(threadQueue.Value); if (threadQueueType == null) { continue; } ulong outerArray = 0; ClrType outerArrayType = null; if (!GetFieldObject(threadQueueType, threadQueue.Value, "m_array", out outerArrayType, out outerArray) || !outerArrayType.IsArray) { continue; } int outerLen = outerArrayType.GetArrayLength(outerArray); for (int i = 0; i < outerLen; ++i) { ulong entry = (ulong)outerArrayType.GetArrayElementValue(outerArray, i); if (entry == 0) { continue; } ClrType entryType = _heap.GetObjectType(entry); if (entryType == null) { continue; } ulong array; ClrType arrayType; if (!GetFieldObject(entryType, entry, "m_array", out arrayType, out array) || !arrayType.IsArray) { continue; } int len = arrayType.GetArrayLength(array); for (int j = 0; j < len; ++j) { ulong addr = (ulong)arrayType.GetArrayElementValue(array, i); if (addr != 0) { yield return(addr); } } } } } } } }