public void VariableRootTest() { // Test to make sure that a specific static and local variable exist. using DataTarget dt = TestTargets.Types.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); ClrHeap heap = runtime.Heap; IEnumerable <IClrRoot> fooRoots = from root in heap.EnumerateRoots() where root.Object.Type.Name == "Foo" select root; IClrRoot[] localVarRoots = fooRoots.Where(r => r.RootKind == ClrRootKind.Stack).ToArray(); ClrThread thread = runtime.GetMainThread(); ClrStackFrame main = thread.GetFrame("Main"); ClrStackFrame inner = thread.GetFrame("Inner"); ulong low = thread.StackBase; ulong high = thread.StackLimit; // Account for different platform stack direction. if (low > high) { ulong tmp = low; low = high; high = tmp; } foreach (IClrRoot localVarRoot in localVarRoots) { Assert.True(low <= localVarRoot.Address && localVarRoot.Address <= high); } }
private static string[] GetClrArgumentsNames(ClrStackFrame frame) { var imd = frame.Module.MetadataImport; var sb = new StringBuilder(64); List <string> arguments = new List <string>(frame.Arguments.Count); IntPtr paramEnum = IntPtr.Zero; uint fetched = 0; int paramDef; imd.EnumParams(ref paramEnum, (int)frame.Method.MetadataToken, out paramDef, 1, out fetched); while (fetched == 1) { int pmd; uint pulSequence, pchName, pdwAttr, pdwCPlusTypeFlag, pcchValue; IntPtr ppValue; imd.GetParamProps(paramDef, out pmd, out pulSequence, sb, (uint)sb.Capacity, out pchName, out pdwAttr, out pdwCPlusTypeFlag, out ppValue, out pcchValue); arguments.Add(sb.ToString()); sb.Clear(); imd.EnumParams(ref paramEnum, (int)frame.Method.MetadataToken, out paramDef, 1, out fetched); } imd.CloseEnum(paramEnum); if (arguments.Count == frame.Arguments.Count - 1) { arguments.Insert(0, "this"); } return(arguments.ToArray()); }
private int FindIlOffset(ClrStackFrame frame) { if (frame.Kind != ClrStackFrameType.ManagedMethod || frame.Method.ILOffsetMap == null) { return(-1); } ulong ip = frame.InstructionPointer; int last = -1; foreach (ILToNativeMap item in frame.Method.ILOffsetMap) { if (item.StartAddress > ip) { return(last); } if (ip <= item.EndAddress) { return(item.ILOffset); } last = item.ILOffset; } return(last); }
public static SDCombinedStackFrame ToSDModel(this ClrStackFrame frame) { StackFrameType type = (frame.Kind == ClrStackFrameType.ManagedMethod) ? StackFrameType.Managed : (frame.Kind == ClrStackFrameType.Runtime) ? StackFrameType.Special : /* here be dragons */ StackFrameType.Special; string methodName; string moduleName = string.Empty; if (frame.Method == null) { methodName = frame.DisplayString; //for example GCFrame } else { methodName = frame.Method.GetFullSignature(); if (frame.Method.Type != null) { moduleName = Path.GetFileNameWithoutExtension(frame.Method.Type.Module.Name); if (string.IsNullOrEmpty(moduleName)) { moduleName = "UNKNOWN"; } } } return(new SDCombinedStackFrame(type, frame.InstructionPointer, frame.StackPointer, methodName, moduleName, frame.Method.NativeCode)); }
private static void SampleCpu(ClrRuntime runtime) { foreach (ClrThread thread in runtime.Threads) { StringBuilder sb = new StringBuilder(); for (int i = thread.StackTrace.Count - 1; i >= 0; i--) { ClrStackFrame stackFrame = thread.StackTrace[i]; if (!string.IsNullOrWhiteSpace(stackFrame.Method?.Type?.Name) || !string.IsNullOrWhiteSpace(stackFrame.Method?.Name)) { sb.Append($"{stackFrame.Method?.Type?.Name}.{stackFrame.Method?.Name};"); } } // Trim the last ';' if (sb.Length > 0 && sb[sb.Length - 1] == ';') { sb.Length = sb.Length - 1; } string stackString = sb.ToString(); if (!string.IsNullOrWhiteSpace(stackString)) { ReportStackTrace(stackString); } runtime.Flush(); } }
public SDCombinedStackFrame(ClrStackFrame frame) { if (frame.Kind == ClrStackFrameType.ManagedMethod) { Type = StackFrameType.Managed; } if (frame.Kind == ClrStackFrameType.Runtime) { Type = StackFrameType.Special; } InstructionPointer = frame.InstructionPointer; StackPointer = frame.StackPointer; if (frame.Method == null) { MethodName = frame.DisplayString; //for example GCFrame return; } MethodName = frame.Method.GetFullSignature(); if (frame.Method.Type != null) { ModuleName = Path.GetFileNameWithoutExtension(frame.Method.Type.Module.Name); } // calculate IL offset with instruction pointer of frame and instruction pointer // in the target dump file of the start of the method's assembly OffsetInMethod = InstructionPointer - frame.Method.NativeCode; }
public static FileAndLineNumber GetSourceLocation(this ClrStackFrame frame) { PdbReader reader = GetReaderForFrame(frame); if (reader is null) { return(default);
public static List <StackFrameInfo> GetDetailedStackTrace(this ClrThread thread) { List <StackFrameInfo> stackframes = new List <StackFrameInfo>(); List <ClrRoot> stackObjects = thread.EnumerateStackObjects().ToList(); ulong lastAddress = 0; foreach (ClrStackFrame frame in thread.StackTrace) { ClrStackFrame f = frame; List <ClrDynamic> objectsInFrame = stackObjects .Where(o => o.Address > lastAddress && o.Address <= f.StackPointer) .OrderBy(o => o.Address) .Select(o => ClrMDSession.Current.Heap.GetDynamicObject(o.Object)) .ToList(); stackframes.Add(new StackFrameInfo { Function = f.DisplayString, Objects = objectsInFrame }); lastAddress = f.StackPointer; } return(stackframes); }
private void ComputeNames(ClrStackFrame frame) { // start by parsing (short)type name var typeName = frame.Method.Type.Name; if (string.IsNullOrEmpty(typeName)) { // IL generated frames TypeName = string.Empty; } else { TypeName = typeName; } // generic methods are not well formatted by ClrMD // foo<...>() => foo[[...]]() #if ClrMD1 var fullName = frame.Method?.GetFullSignature(); #else var fullName = frame.Method?.Signature; #endif MethodName = frame.Method.Name; if (MethodName.EndsWith("]]")) { // fix ClrMD bug with method name MethodName = GetGenericMethodName(fullName); } Signature.AddRange(BuildSignature(fullName)); }
internal DbgStackFrameInfo(DbgEngDebugger debugger, DbgUModeThreadInfo thread, DEBUG_STACK_FRAME_EX nativeFrame, ClrStackFrame managedFrame) : this(debugger, thread, nativeFrame, managedFrame, true) { }
private FileAndLineNumber GetSourceLocation(ClrStackFrame frame) { var reader = GetReaderForFrame(frame); if (reader != null) { var method = frame.Method; var result = reader.GetMethod((int)method.MetadataToken, out ISymUnmanagedMethod methodSym); if (methodSym != null) { var seqPoints = methodSym.GetSequencePoints(); var ilOffset = FindIlOffset(frame); if (ilOffset >= 0) { var nearest = FindNearestLine(seqPoints, ilOffset); if (nearest.Line == PdbHiddenLine) { nearest.Line = 0; } _logger?.LogTrace("FindNearestLine for {0} in method {1} returning {2} in {3}", ilOffset, method.Name, nearest.Line, nearest.File); return(nearest); } } } return(default(FileAndLineNumber)); }
public ClrStackRoot(ulong address, ClrObject obj, ClrStackFrame stackFrame, bool interior, bool pinned) { Address = address; Object = obj; StackFrame = stackFrame; IsInterior = interior; IsPinned = pinned; }
public StackFrame(ClrStackFrame frame) { var signature = frame.Method?.Signature; Text = string.IsNullOrEmpty(signature) ? "?" : string.Intern(signature); Signature = new List <string>(); ComputeNames(frame); }
public ThreadStackFrame(ClrStackFrame clrStackFrame) { if (clrStackFrame.Method != null) { Method = new MethodRef(clrStackFrame.Method); } DisplayName = clrStackFrame.DisplayString; }
private string GetFrameInformation(ClrThread thread, ClrStackFrame frame, ClrStackFrame firstFrame) { // get the method call from the given frame string info = ""; var sourceLocation = frame.GetFileAndLineNumber(); if (sourceLocation == null) { info = frame.DisplayString; } else // it seems that GetFileAndLineNumber() does not work --> need to figure out what is the other ClrMD API to dig into the symbols { info = frame.DisplayString + "[" + sourceLocation.FilePath + ", Line " + sourceLocation.LineNumber.ToString() + "]"; } // look for locking information if (firstFrame.Method.Name.Contains("Wait") || (firstFrame.Method.Name == "Enter") && (firstFrame.Method.Type.Name == "System.Threading.Monitor")) { // special case for MonitorEnter --> not a WaitHandle to wait on bool isMonitorEnter = (firstFrame.Method.Name == "Enter") && (firstFrame.Method.Type.Name == "System.Threading.Monitor"); info = info + "\r\n => " + firstFrame.Method.Type.Name + "." + firstFrame.Method.Name; // look for object used as lock int maxStackObjects = 10; foreach (var so in thread.EnumerateStackObjects(true)) { if (so == null) { continue; } var type = so.Type; if (so.Type == null) { continue; } string typeName = so.Type.Name; if (typeName.Contains("WaitHandle") || isMonitorEnter) { info = info + string.Format("({0} = 0x{1:X16})\r\n", typeName, so.Object); break; } else { } maxStackObjects--; if (maxStackObjects == 0) { break; } } } return(info); }
public ClrStackFrameCloneable(ClrStackFrame actual) { if (null == actual) { throw new ArgumentNullException("actual"); } m_actual = actual; } // end constructor
public ClrStackInteriorRoot(ClrSegment seg, ulong address, ulong objAddr, ClrStackFrame stackFrame, bool pinned) { _segment = seg; ObjectPointer = objAddr; Address = address; StackFrame = stackFrame; IsPinned = pinned; }
private static StackFrameInfo GetStackFrameInfo(ClrStackFrame frame) { return (new StackFrameInfo { StackPointer = frame.StackPointer, InstructionPointer = frame.InstructionPointer, DisplayString = frame.DisplayString }); }
public StackFrame(ClrStackFrame frame) { #if ClrMD1 Text = string.Intern(frame.DisplayString); #else var signature = frame.Method?.Signature; Text = string.IsNullOrEmpty(signature) ? "?" : string.Intern(signature); #endif Signature = new List <string>(); ComputeNames(frame); }
public LocalVarRoot(ulong addr, ulong obj, ClrType type, ClrAppDomain domain, ClrThread thread, bool pinned, bool falsePos, bool interior, ClrStackFrame stackFrame) { Address = addr; Object = obj; _pinned = pinned; _falsePos = falsePos; _interior = interior; _domain = domain; _thread = thread; _type = type; _stackFrame = stackFrame; }
public LocalVarRoot(ulong addr, ulong obj, ClrType type, ClrAppDomain domain, ClrThread thread, bool pinned, bool falsePos, bool interior, ClrStackFrame stackFrame) { Address = addr; Object = obj; IsPinned = pinned; IsPossibleFalsePositive = falsePos; IsInterior = interior; AppDomain = domain; Thread = thread; Type = type; StackFrame = stackFrame; }
private ISymUnmanagedReader GetReaderForFrame(ClrStackFrame frame) { ClrModule module = frame.Method?.Type?.Module; PdbInfo info = module?.Pdb; ISymUnmanagedReader reader = null; string name = string.Empty; if (info != null) { if (_pdbReaders.TryGetValue(info, out reader)) { return(reader); } name = Path.GetFileName(info.FileName); if (!File.Exists(name)) { _logger?.LogTrace("Symbol file {0} missing", name); return(null); } try { Stream stream = File.OpenRead(name); if (IsPortablePdb(stream)) { var bindar = new SymBinder(); int result = bindar.GetReaderFromPdbFile(new MetaDataImportProvider(module.MetadataImport), name, out reader); } else { reader = SymUnmanagedReaderFactory.CreateReaderWithMetadataImport <ISymUnmanagedReader3>(stream, module.MetadataImport, SymUnmanagedReaderCreationOptions.Default); } } catch (Exception e) { _logger?.LogError(e, "Unable to obtain symbol reader for {0}", name); } } if (reader != null) { _logger?.LogTrace("Symbol file {0} found, reader created", name); _pdbReaders.Add(info, reader); } else { _logger?.LogTrace("Unable to obtain symbol reader for {0}", name); } return(reader); }
public static FileAndLineNumber FileAndLineNumber(this ClrStackFrame frame) { PdbReader reader = GetReaderForFrame(frame); if (reader == null) { return(new FileAndLineNumber()); } PdbFunction function = reader.GetFunctionFromToken(frame.Method.MetadataToken); int ilOffset = FindIlOffset(frame); return(FindNearestLine(function, ilOffset)); }
public static SourceLocation GetSourceLocation(this ClrStackFrame frame) { PdbReader reader = GetReaderForMethod(frame.Method); if (reader == null) { return(null); } PdbFunction function = reader.GetFunctionFromToken(frame.Method.MetadataToken); int ilOffset = FindIlOffset(frame); return(FindNearestLine(function, ilOffset)); }
public StackFrameInformation(ClrDump clrDump, ClrStackFrame frame) { this.clrDump = clrDump; this.frame = frame; DisplayString = frame.DisplayString; Kind = frame.Kind; Method = frame.Method; #if LINE_AND_FILE if (frame.Kind != ClrStackFrameType.Runtime) { fileAndLineNumber = clrDump.Eval(() => frame.FileAndLineNumber()); } #endif }
private string GetFrameInformation(ClrThread thread, ClrStackFrame frame, ClrStackFrame firstFrame) { // get the method call from the given frame string info = frame.DisplayString; // look for locking information if (firstFrame.Method.Name.Contains("Wait") || (firstFrame.Method.Name == "Enter") && (firstFrame.Method.Type.Name == "System.Threading.Monitor")) { // special case for MonitorEnter --> not a WaitHandle to wait on bool isMonitorEnter = (firstFrame.Method.Name == "Enter") && (firstFrame.Method.Type.Name == "System.Threading.Monitor"); info = info + "\r\n => " + firstFrame.Method.Type.Name + "." + firstFrame.Method.Name; // look for object used as lock int maxStackObjects = 10; foreach (var so in thread.EnumerateStackObjects(true)) { if (so == null) { continue; } var type = so.Type; if (so.Type == null) { continue; } string typeName = so.Type.Name; if (typeName.Contains("WaitHandle") || isMonitorEnter) { info = info + string.Format("({0} = 0x{1:X16})\r\n", typeName, so.Object); break; } else { } maxStackObjects--; if (maxStackObjects == 0) { break; } } } return(info); }
public int Next(out ulong pIP, out ulong pSP, out string pFunction) { if (m_curr < m_frames.Count) { ClrStackFrame frame = m_frames[m_curr]; pIP = frame.InstructionPointer; pSP = frame.StackPointer; pFunction = frame.ToString(); return(HRESULTS.S_OK); } m_curr++; pIP = 0; pSP = 0; pFunction = null; return((m_curr == m_frames.Count) ? HRESULTS.S_FALSE : HRESULTS.E_FAIL); }
private IEnumerable <ClrRoot> EnumerateStackReferencesWorker(ClrThread thread) { using (SOSStackRefEnum stackRefEnum = _sos.EnumerateStackRefs(thread.OSThreadId)) { if (stackRefEnum == null) { yield break; } ClrAppDomain domain = GetAppDomainByAddress(thread.AppDomain); ClrHeap heap = Heap; StackRefData[] refs = new StackRefData[1024]; const int GCInteriorFlag = 1; const int GCPinnedFlag = 2; int fetched = 0; while ((fetched = stackRefEnum.ReadStackReferences(refs)) != 0) { for (uint i = 0; i < fetched && i < refs.Length; ++i) { if (refs[i].Object == 0) { continue; } bool pinned = (refs[i].Flags & GCPinnedFlag) == GCPinnedFlag; bool interior = (refs[i].Flags & GCInteriorFlag) == GCInteriorFlag; ClrType type = null; if (!interior) { type = heap.GetObjectType(refs[i].Object); } ClrStackFrame frame = thread.StackTrace.SingleOrDefault( f => f.StackPointer == refs[i].Source || f.StackPointer == refs[i].StackPointer && f.InstructionPointer == refs[i].Source); if (interior || type != null) { yield return(new LocalVarRoot(refs[i].Address, refs[i].Object, type, domain, thread, pinned, false, interior, frame)); } } } } }
internal DbgStackFrameInfo(DbgEngDebugger debugger, DbgUModeThreadInfo thread, DEBUG_STACK_FRAME_EX nativeFrame, ClrStackFrame managedFrame, bool alreadySearchManagedFrames) : base(debugger) { if (null == thread) { throw new ArgumentNullException("thread"); } NativeFrameEx = nativeFrame; Thread = thread; m_managedFrame = managedFrame; m_alreadySearchedManagedFrames = alreadySearchManagedFrames; } // end constructor()
public static SDFileAndLineNumber GetSourceLocation(this ClrStackFrame frame) { try { PdbReader reader = GetReaderForFrame(frame); if (reader == null) { return(null); } PdbFunction function = reader.GetFunctionFromToken(frame.Method.MetadataToken); int ilOffset = FindIlOffset(frame); return(FindNearestLine(function, ilOffset)); } catch (Exception e) { Console.WriteLine($"exception in {nameof(GetSourceLocation)}: {e}"); return(null); } }