public StackFrameHelper(Thread target) { targetThread = target; rgMethodBase = null; rgMethodHandle = null; rgiMethodToken = null; rgiOffset = null; rgiILOffset = null; rgAssemblyPath = null; rgLoadedPeAddress = null; rgiLoadedPeSize = null; rgInMemoryPdbAddress = null; rgiInMemoryPdbSize = null; dynamicMethods = null; rgFilename = null; rgiLineNumber = null; rgiColumnNumber = null; getSourceLineInfo = null; #if FEATURE_EXCEPTIONDISPATCHINFO rgiLastFrameFromForeignExceptionStackTrace = null; #endif // FEATURE_EXCEPTIONDISPATCHINFO // 0 means capture all frames. For StackTraces from an Exception, the EE always // captures all frames. For other uses of StackTraces, we can abort stack walking after // some limit if we want to by setting this to a non-zero value. In Whidbey this was // hard-coded to 512, but some customers complained. There shouldn't be any need to limit // this as memory/CPU is no longer allocated up front. If there is some reason to provide a // limit in the future, then we should expose it in the managed API so applications can // override it. iFrameCount = 0; }
// // Initializes the stack trace helper. If fNeedFileInfo is true, initializes rgFilename, // rgiLineNumber and rgiColumnNumber fields using the portable PDB reader if not already // done by GetStackFramesInternal (on Windows for old PDB format). // internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exception) { StackTrace.GetStackFramesInternal(this, iSkip, fNeedFileInfo, exception); if (!fNeedFileInfo) { return; } // Check if this function is being reentered because of an exception in the code below if (t_reentrancy > 0) { return; } t_reentrancy++; try { if (s_symbolsMethodInfo == null) { s_symbolsType = Type.GetType("System.Diagnostics.StackTraceSymbols, System.Diagnostics.StackTrace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false); if (s_symbolsType == null) { return; } s_symbolsMethodInfo = s_symbolsType.GetMethod("GetSourceLineInfo"); if (s_symbolsMethodInfo == null) { return; } } if (getSourceLineInfo == null) { // Create an instance of System.Diagnostics.Stacktrace.Symbols object target = Activator.CreateInstance(s_symbolsType); // Create an instance delegate for the GetSourceLineInfo method getSourceLineInfo = (GetSourceLineInfoDelegate)s_symbolsMethodInfo.CreateDelegate(typeof(GetSourceLineInfoDelegate), target); } for (int index = 0; index < iFrameCount; index++) { // If there was some reason not to try get get the symbols from the portable PDB reader like the module was // ENC or the source/line info was already retrieved, the method token is 0. if (rgiMethodToken[index] != 0) { getSourceLineInfo(rgAssemblyPath[index], rgLoadedPeAddress[index], rgiLoadedPeSize[index], rgInMemoryPdbAddress[index], rgiInMemoryPdbSize[index], rgiMethodToken[index], rgiILOffset[index], out rgFilename[index], out rgiLineNumber[index], out rgiColumnNumber[index]); } } } finally { t_reentrancy--; } }
// // Initializes the stack trace helper. If fNeedFileInfo is true, initializes rgFilename, // rgiLineNumber and rgiColumnNumber fields using the portable PDB reader if not already // done by GetStackFramesInternal (on Windows for old PDB format). // internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception?exception) { StackTrace.GetStackFramesInternal(this, iSkip, fNeedFileInfo, exception); if (!fNeedFileInfo) { return; } // Check if this function is being reentered because of an exception in the code below if (t_reentrancy > 0) { return; } t_reentrancy++; try { if (s_getSourceLineInfo == null) { Type?symbolsType = Type.GetType( "System.Diagnostics.StackTraceSymbols, System.Diagnostics.StackTrace, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false); if (symbolsType == null) { return; } Type[] parameterTypes = new Type[] { typeof(Assembly), typeof(string), typeof(IntPtr), typeof(int), typeof(bool), typeof(IntPtr), typeof(int), typeof(int), typeof(int), typeof(string).MakeByRefType(), typeof(int).MakeByRefType(), typeof(int).MakeByRefType() }; MethodInfo?symbolsMethodInfo = symbolsType.GetMethod("GetSourceLineInfo", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, parameterTypes, null); if (symbolsMethodInfo == null) { return; } // Create an instance of System.Diagnostics.Stacktrace.Symbols object?target = Activator.CreateInstance(symbolsType); // Create an instance delegate for the GetSourceLineInfo method GetSourceLineInfoDelegate getSourceLineInfo = symbolsMethodInfo.CreateDelegate <GetSourceLineInfoDelegate>(target); // We could race with another thread. It doesn't matter if we win or lose, the losing instance will be GC'ed and all threads including this one will // use the winning instance Interlocked.CompareExchange(ref s_getSourceLineInfo, getSourceLineInfo, null); } for (int index = 0; index < iFrameCount; index++) { // If there was some reason not to try get the symbols from the portable PDB reader like the module was // ENC or the source/line info was already retrieved, the method token is 0. if (rgiMethodToken ![index] != 0)
// // Initializes the stack trace helper. If fNeedFileInfo is true, initializes rgFilename, // rgiLineNumber and rgiColumnNumber fields using the portable PDB reader if not already // done by GetStackFramesInternal (on Windows for old PDB format). // internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exception) { StackTrace.GetStackFramesInternal(this, iSkip, fNeedFileInfo, exception); if (!fNeedFileInfo) return; // Check if this function is being reentered because of an exception in the code below if (t_reentrancy > 0) return; t_reentrancy++; try { if (s_symbolsMethodInfo == null) { s_symbolsType = Type.GetType( "System.Diagnostics.StackTraceSymbols, System.Diagnostics.StackTrace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false); if (s_symbolsType == null) return; s_symbolsMethodInfo = s_symbolsType.GetMethod("GetSourceLineInfo"); if (s_symbolsMethodInfo == null) return; } if (getSourceLineInfo == null) { // Create an instance of System.Diagnostics.Stacktrace.Symbols object target = Activator.CreateInstance(s_symbolsType); // Create an instance delegate for the GetSourceLineInfo method getSourceLineInfo = (GetSourceLineInfoDelegate)s_symbolsMethodInfo.CreateDelegate(typeof(GetSourceLineInfoDelegate), target); } for (int index = 0; index < iFrameCount; index++) { // If there was some reason not to try get get the symbols from the portable PDB reader like the module was // ENC or the source/line info was already retrieved, the method token is 0. if (rgiMethodToken[index] != 0) { getSourceLineInfo(rgAssemblyPath[index], rgLoadedPeAddress[index], rgiLoadedPeSize[index], rgInMemoryPdbAddress[index], rgiInMemoryPdbSize[index], rgiMethodToken[index], rgiILOffset[index], out rgFilename[index], out rgiLineNumber[index], out rgiColumnNumber[index]); } } } catch { } finally { t_reentrancy--; } }
// // Initializes the stack trace helper. If fNeedFileInfo is true, initializes rgFilename, // rgiLineNumber and rgiColumnNumber fields using the portable PDB reader if not already // done by GetStackFramesInternal (on Windows for old PDB format). // internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exception) { StackTrace.GetStackFramesInternal(this, iSkip, fNeedFileInfo, exception); if (!fNeedFileInfo) { return; } // Check if this function is being reentered because of an exception in the code below if (t_reentrancy > 0) { return; } t_reentrancy++; try { if (s_getSourceLineInfo == null) { Type symbolsType = Type.GetType( "System.Diagnostics.StackTraceSymbols, System.Diagnostics.StackTrace, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false); if (symbolsType == null) { return; } MethodInfo symbolsMethodInfo = symbolsType.GetMethod("GetSourceLineInfo", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (symbolsMethodInfo == null) { return; } // Create an instance of System.Diagnostics.Stacktrace.Symbols object target = Activator.CreateInstance(symbolsType); // Create an instance delegate for the GetSourceLineInfo method GetSourceLineInfoDelegate getSourceLineInfo = (GetSourceLineInfoDelegate)symbolsMethodInfo.CreateDelegate(typeof(GetSourceLineInfoDelegate), target); // We could race with another thread. It doesn't matter if we win or lose, the losing instance will be GC'ed and all threads including this one will // use the winning instance Interlocked.CompareExchange(ref s_getSourceLineInfo, getSourceLineInfo, null); } for (int index = 0; index < iFrameCount; index++) { // If there was some reason not to try get the symbols from the portable PDB reader like the module was // ENC or the source/line info was already retrieved, the method token is 0. if (rgiMethodToken[index] != 0) { s_getSourceLineInfo(rgAssemblyPath[index], rgLoadedPeAddress[index], rgiLoadedPeSize[index], rgInMemoryPdbAddress[index], rgiInMemoryPdbSize[index], rgiMethodToken[index], rgiILOffset[index], out rgFilename[index], out rgiLineNumber[index], out rgiColumnNumber[index]); } } } catch { } finally { t_reentrancy--; } }
internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exception) { StackTrace.GetStackFramesInternal(this, iSkip, fNeedFileInfo, exception); if (!fNeedFileInfo) { return; } // For back compat we opt-out of using Portable PDBs before 4.7.2. See the comments in // RuntimeFeature for more details. // // Even if our compat policy for enabling the feature changes, make sure that // RuntimeFeature.IsSupported accurately encapsulates that policy. Our API contract with // tools is that we will accurately tell them whether or not Portable PDB is supported. if (!RuntimeFeature.IsSupported(RuntimeFeature.PortablePdb)) { return; } // Check if this function is being reentered because of an exception in the code below if (t_reentrancy > 0) { return; } t_reentrancy++; try { // need private reflection below + unmanaged code for the portable PDB access itself // PERF: these demands are somewhat expensive so do the quick check first. We are aiming for // ~50k traces/s at 5 frames/trace on decent 2017 era hardware to maintain rough performance // parity with 4.7 implementation that didn't have Portable PDB support if (!CodeAccessSecurityEngine.QuickCheckForAllDemands()) { new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert(); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); } if (s_getSourceLineInfo == null) { Type symbolsType = Type.GetType( "System.Diagnostics.StackTraceSymbols, System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", throwOnError: false); if (symbolsType == null) { return; } MethodInfo symbolsMethodInfo = symbolsType.GetMethod("GetSourceLineInfoWithoutCasAssert", new Type[] { typeof(string), typeof(IntPtr), typeof(int), typeof(IntPtr), typeof(int), typeof(int), typeof(int), typeof(string).MakeByRefType(), typeof(int).MakeByRefType(), typeof(int).MakeByRefType() }); // We can't take a servicing dependency that System.Core.dll has been upgraded. If for whatever // wacky reason we still have the old version of System.Core.dll fallback to the original less // performant implementation of the method. if (symbolsMethodInfo == null) { symbolsMethodInfo = symbolsType.GetMethod("GetSourceLineInfo", new Type[] { typeof(string), typeof(IntPtr), typeof(int), typeof(IntPtr), typeof(int), typeof(int), typeof(int), typeof(string).MakeByRefType(), typeof(int).MakeByRefType(), typeof(int).MakeByRefType() }); } if (symbolsMethodInfo == null) { return; } // Create an instance of System.Diagnostics.Stacktrace.Symbols object target = Activator.CreateInstance(symbolsType); // Create an instance delegate for the GetSourceLineInfo method GetSourceLineInfoDelegate getSourceLineInfo = (GetSourceLineInfoDelegate)symbolsMethodInfo.CreateDelegate(typeof(GetSourceLineInfoDelegate), target); // We could ---- with another thread. It doesn't matter if we win or lose, the losing instance will be GC'ed and all threads including this one will // use the winning instance Interlocked.CompareExchange(ref s_getSourceLineInfo, getSourceLineInfo, null); } for (int index = 0; index < iFrameCount; index++) { // If there was some reason not to try get get the symbols from the portable PDB reader like the module was // ENC or the source/line info was already retrieved, the method token is 0. if (rgiMethodToken[index] != 0) { s_getSourceLineInfo(rgAssemblyPath[index], rgLoadedPeAddress[index], rgiLoadedPeSize[index], rgInMemoryPdbAddress[index], rgiInMemoryPdbSize[index], rgiMethodToken[index], rgiILOffset[index], out rgFilename[index], out rgiLineNumber[index], out rgiColumnNumber[index]); } } } catch { } finally { t_reentrancy--; } }