public void GetThreadTebTest() { using DataTarget dt = TestTargets.AppDomains.LoadFullDumpWithDbgEng(); IThreadReader threadReader = (IThreadReader)dt.DataReader; using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); using SOSDac dac = runtime.DacLibrary.SOSDacInterface; foreach (ClrThread thread in runtime.Threads) { if (!thread.IsAlive) { continue; } Assert.NotEqual(0u, thread.OSThreadId); ulong teb = threadReader.GetThreadTeb(thread.OSThreadId); Assert.NotEqual(0ul, teb); if (dac.GetThreadData(thread.Address, out ThreadData threadData)) { Assert.Equal((ulong)threadData.Teb, teb); } } }
public void EnsureOSThreadOrdering() { using DataTarget dt = TestTargets.Types.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); IThreadReader threadReader = (IThreadReader)dt.DataReader; var items = threadReader.EnumerateOSThreadIds().ToArray(); uint mainThreadId = runtime.GetMainThread().OSThreadId; Assert.Equal(mainThreadId, threadReader.EnumerateOSThreadIds().First()); }
public void EnumerateOSThreadIdsTest() { using DataTarget dt = TestTargets.Types.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); IThreadReader threadReader = (IThreadReader)dt.DataReader; uint[] threads = threadReader.EnumerateOSThreadIds().ToArray(); Assert.NotEmpty(threads); Assert.DoesNotContain(0u, threads); // no duplicates Assert.Equal(threads.Length, new HashSet <uint>(threads).Count); foreach (uint threadId in runtime.Threads.Select(f => f.OSThreadId).Where(id => id != 0)) { Assert.Contains(threadId, threads); } }
public ThreadServiceFromDataReader(ITarget target, IDataReader dataReader) : base(target) { _dataReader = dataReader; _threadReader = (IThreadReader)dataReader; if (dataReader is IThreadReader threadReader) { // Initialize the current thread IEnumerable <uint> threads = threadReader.EnumerateOSThreadIds(); if (threads.Any()) { CurrentThreadId = threads.First(); } } else { throw new InvalidOperationException("IThreadReader not implemented"); } }
public ThreadService(IDataReader dataReader) { _dataReader = dataReader; _threadReader = (IThreadReader)dataReader; Type contextType; switch (dataReader.Architecture) { case Architecture.Amd64: // Dumps generated with newer dbgeng have bigger context buffers and clrmd requires the context size to at least be that size. _contextSize = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? 0x700 : AMD64Context.Size; _contextFlags = AMD64Context.ContextControl | AMD64Context.ContextInteger | AMD64Context.ContextSegments; contextType = typeof(AMD64Context); break; case Architecture.X86: _contextSize = X86Context.Size; _contextFlags = X86Context.ContextControl | X86Context.ContextInteger | X86Context.ContextSegments; contextType = typeof(X86Context); break; case Architecture.Arm64: _contextSize = Arm64Context.Size; _contextFlags = Arm64Context.ContextControl | Arm64Context.ContextInteger; contextType = typeof(Arm64Context); break; case Architecture.Arm: _contextSize = ArmContext.Size; _contextFlags = ArmContext.ContextControl | ArmContext.ContextInteger; contextType = typeof(ArmContext); break; default: throw new PlatformNotSupportedException($"Unsupported architecture: {dataReader.Architecture}"); } var registers = new List <RegisterInfo>(); int index = 0; FieldInfo[] fields = contextType.GetFields(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo field in fields) { RegisterAttribute registerAttribute = field.GetCustomAttributes <RegisterAttribute>(inherit: false).SingleOrDefault(); if (registerAttribute == null) { continue; } RegisterType registerType = registerAttribute.RegisterType & RegisterType.TypeMask; switch (registerType) { case RegisterType.Control: case RegisterType.General: case RegisterType.Segments: break; default: continue; } if ((registerAttribute.RegisterType & RegisterType.ProgramCounter) != 0) { _instructionPointerIndex = index; } if ((registerAttribute.RegisterType & RegisterType.StackPointer) != 0) { _stackPointerIndex = index; } if ((registerAttribute.RegisterType & RegisterType.FramePointer) != 0) { _framePointerIndex = index; } FieldOffsetAttribute offsetAttribute = field.GetCustomAttributes <FieldOffsetAttribute>(inherit: false).Single(); var registerInfo = new RegisterInfo(index, offsetAttribute.Value, Marshal.SizeOf(field.FieldType), registerAttribute.Name ?? field.Name.ToLower()); registers.Add(registerInfo); index++; } _lookupByName = registers.ToDictionary((info) => info.RegisterName); _lookupByIndex = registers.ToDictionary((info) => info.RegisterIndex); _registers = registers; }
public ThreadServiceFromDataReader(ITarget target, IDataReader dataReader) : base(target) { _dataReader = dataReader; _threadReader = (IThreadReader)dataReader; }