<Compile Include="$(BclSourcesRoot)\System\Diagnostics\Debugger.cs" />
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\ICustomDebuggerNotification.cs" />
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\Stacktrace.cs" />
- <Compile Include="$(BclSourcesRoot)\System\Diagnostics\Stackframe.cs" />
+ <Compile Include="$(BclSourcesRoot)\System\Diagnostics\StackFrame.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\EditAndContinueHelper.cs" />
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventSource_CoreCLR.cs" />
<Compile Condition="'$(FeatureXplatEventSource)' == 'true'" Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\XplatEventLogger.cs" />
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Text;
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace System.Diagnostics
+{
+ /// <summary>
+ /// There is no good reason for the methods of this class to be virtual.
+ /// </summary>
+ public partial class StackFrame
+ {
+ /// <summary>
+ /// Called from the class "StackTrace"
+ /// </summary>
+ internal StackFrame(bool DummyFlag1, bool DummyFlag2)
+ {
+ InitMembers();
+ }
+
+ private void BuildStackFrame(int skipFrames, bool needFileInfo)
+ {
+ StackFrameHelper StackF = new StackFrameHelper(null);
+
+ StackF.InitializeSourceInfo(0, needFileInfo, null);
+
+ int iNumOfFrames = StackF.GetNumberOfFrames();
+
+ skipFrames += StackTrace.CalculateFramesToSkip(StackF, iNumOfFrames);
+
+ if ((iNumOfFrames - skipFrames) > 0)
+ {
+ _method = StackF.GetMethodBase(skipFrames);
+ _nativeOffset = StackF.GetOffset(skipFrames);
+ _ilOffset = StackF.GetILOffset(skipFrames);
+ if (needFileInfo)
+ {
+ _fileName = StackF.GetFilename(skipFrames);
+ _lineNumber = StackF.GetLineNumber(skipFrames);
+ _columnNumber = StackF.GetColumnNumber(skipFrames);
+ }
+ }
+ }
+
+ private bool AppendStackFrameWithoutMethodBase(StringBuilder sb) => false;
+ }
+}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-
-using System.Text;
-using System;
-using System.IO;
-using System.Reflection;
-
-namespace System.Diagnostics
-{
- // There is no good reason for the methods of this class to be virtual.
- public class StackFrame
- {
- private MethodBase method;
- private int offset;
- private int ILOffset;
- private String strFileName;
- private int iLineNumber;
- private int iColumnNumber;
-
- [System.Runtime.Serialization.OptionalField]
- private bool fIsLastFrameFromForeignExceptionStackTrace;
-
- internal void InitMembers()
- {
- method = null;
- offset = OFFSET_UNKNOWN;
- ILOffset = OFFSET_UNKNOWN;
- strFileName = null;
- iLineNumber = 0;
- iColumnNumber = 0;
- fIsLastFrameFromForeignExceptionStackTrace = false;
- }
-
- // Constructs a StackFrame corresponding to the active stack frame.
- public StackFrame()
- {
- InitMembers();
- BuildStackFrame(0 + StackTrace.METHODS_TO_SKIP, false);// iSkipFrames=0
- }
-
- // Constructs a StackFrame corresponding to the active stack frame.
- public StackFrame(bool fNeedFileInfo)
- {
- InitMembers();
- BuildStackFrame(0 + StackTrace.METHODS_TO_SKIP, fNeedFileInfo);// iSkipFrames=0
- }
-
- // Constructs a StackFrame corresponding to a calling stack frame.
- //
- public StackFrame(int skipFrames)
- {
- InitMembers();
- BuildStackFrame(skipFrames + StackTrace.METHODS_TO_SKIP, false);
- }
-
- // Constructs a StackFrame corresponding to a calling stack frame.
- //
- public StackFrame(int skipFrames, bool fNeedFileInfo)
- {
- InitMembers();
- BuildStackFrame(skipFrames + StackTrace.METHODS_TO_SKIP, fNeedFileInfo);
- }
-
-
- // Called from the class "StackTrace"
- //
- internal StackFrame(bool DummyFlag1, bool DummyFlag2)
- {
- InitMembers();
- }
-
- // Constructs a "fake" stack frame, just containing the given file
- // name and line number. Use when you don't want to use the
- // debugger's line mapping logic.
- //
- public StackFrame(String fileName, int lineNumber)
- {
- InitMembers();
- BuildStackFrame(StackTrace.METHODS_TO_SKIP, false);
- strFileName = fileName;
- iLineNumber = lineNumber;
- iColumnNumber = 0;
- }
-
-
- // Constructs a "fake" stack frame, just containing the given file
- // name, line number and column number. Use when you don't want to
- // use the debugger's line mapping logic.
- //
- public StackFrame(String fileName, int lineNumber, int colNumber)
- {
- InitMembers();
- BuildStackFrame(StackTrace.METHODS_TO_SKIP, false);
- strFileName = fileName;
- iLineNumber = lineNumber;
- iColumnNumber = colNumber;
- }
-
-
- // Constant returned when the native or IL offset is unknown
- public const int OFFSET_UNKNOWN = -1;
-
-
- internal virtual void SetMethodBase(MethodBase mb)
- {
- method = mb;
- }
-
- internal virtual void SetOffset(int iOffset)
- {
- offset = iOffset;
- }
-
- internal virtual void SetILOffset(int iOffset)
- {
- ILOffset = iOffset;
- }
-
- internal virtual void SetFileName(String strFName)
- {
- strFileName = strFName;
- }
-
- internal virtual void SetLineNumber(int iLine)
- {
- iLineNumber = iLine;
- }
-
- internal virtual void SetColumnNumber(int iCol)
- {
- iColumnNumber = iCol;
- }
-
- internal virtual void SetIsLastFrameFromForeignExceptionStackTrace(bool fIsLastFrame)
- {
- fIsLastFrameFromForeignExceptionStackTrace = fIsLastFrame;
- }
-
- internal virtual bool GetIsLastFrameFromForeignExceptionStackTrace()
- {
- return fIsLastFrameFromForeignExceptionStackTrace;
- }
-
- // Returns the method the frame is executing
- //
- public virtual MethodBase GetMethod()
- {
- return method;
- }
-
- // Returns the offset from the start of the native (jitted) code for the
- // method being executed
- //
- public virtual int GetNativeOffset()
- {
- return offset;
- }
-
-
- // Returns the offset from the start of the IL code for the
- // method being executed. This offset may be approximate depending
- // on whether the jitter is generating debuggable code or not.
- //
- public virtual int GetILOffset()
- {
- return ILOffset;
- }
-
- // Returns the file name containing the code being executed. This
- // information is normally extracted from the debugging symbols
- // for the executable.
- //
- public virtual String GetFileName()
- {
- return strFileName;
- }
-
- // Returns the line number in the file containing the code being executed.
- // This information is normally extracted from the debugging symbols
- // for the executable.
- //
- public virtual int GetFileLineNumber()
- {
- return iLineNumber;
- }
-
- // Returns the column number in the line containing the code being executed.
- // This information is normally extracted from the debugging symbols
- // for the executable.
- //
- public virtual int GetFileColumnNumber()
- {
- return iColumnNumber;
- }
-
-
- // Builds a readable representation of the stack frame
- //
- public override String ToString()
- {
- StringBuilder sb = new StringBuilder(255);
-
- if (method != null)
- {
- sb.Append(method.Name);
-
- // deal with the generic portion of the method
- if (method is MethodInfo && ((MethodInfo)method).IsGenericMethod)
- {
- Type[] typars = ((MethodInfo)method).GetGenericArguments();
-
- sb.Append('<');
- int k = 0;
- bool fFirstTyParam = true;
- while (k < typars.Length)
- {
- if (fFirstTyParam == false)
- sb.Append(',');
- else
- fFirstTyParam = false;
-
- sb.Append(typars[k].Name);
- k++;
- }
-
- sb.Append('>');
- }
-
- sb.Append(" at offset ");
- if (offset == OFFSET_UNKNOWN)
- sb.Append("<offset unknown>");
- else
- sb.Append(offset);
-
- sb.Append(" in file:line:column ");
-
- bool useFileName = (strFileName != null);
-
- if (!useFileName)
- sb.Append("<filename unknown>");
- else
- sb.Append(strFileName);
- sb.Append(':');
- sb.Append(iLineNumber);
- sb.Append(':');
- sb.Append(iColumnNumber);
- }
- else
- {
- sb.Append("<null>");
- }
- sb.Append(Environment.NewLine);
-
- return sb.ToString();
- }
-
-
- private void BuildStackFrame(int skipFrames, bool fNeedFileInfo)
- {
- StackFrameHelper StackF = new StackFrameHelper(null);
-
- StackF.InitializeSourceInfo(0, fNeedFileInfo, null);
-
- int iNumOfFrames = StackF.GetNumberOfFrames();
-
- skipFrames += StackTrace.CalculateFramesToSkip(StackF, iNumOfFrames);
-
- if ((iNumOfFrames - skipFrames) > 0)
- {
- method = StackF.GetMethodBase(skipFrames);
- offset = StackF.GetOffset(skipFrames);
- ILOffset = StackF.GetILOffset(skipFrames);
- if (fNeedFileInfo)
- {
- strFileName = StackF.GetFilename(skipFrames);
- iLineNumber = StackF.GetLineNumber(skipFrames);
- iColumnNumber = StackF.GetColumnNumber(skipFrames);
- }
- }
- }
- }
-}
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebuggerStepperBoundaryAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebuggerTypeProxyAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebuggerVisualizerAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\StackFrame.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\StackTraceHiddenAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DivideByZeroException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DllNotFoundException.cs" />
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Text;
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace System.Diagnostics
+{
+ /// <summary>
+ /// There is no good reason for the methods of this class to be virtual.
+ /// </summary>
+ public partial class StackFrame
+ {
+ /// <summary>
+ /// Reflection information for the method if available, null otherwise.
+ /// </summary>
+ private MethodBase _method;
+
+ /// <summary>
+ /// Native offset of the current instruction within the current method if available,
+ /// OFFSET_UNKNOWN otherwise.
+ /// </summary>
+ private int _nativeOffset;
+
+ /// <summary>
+ /// IL offset of the current instruction within the current method if available,
+ /// OFFSET_UNKNOWN otherwise.
+ /// </summary>
+ private int _ilOffset;
+
+ /// <summary>
+ /// Source file name representing the current code location if available, null otherwise.
+ /// </summary>
+ private string _fileName;
+
+ /// <summary>
+ /// Line number representing the current code location if available, 0 otherwise.
+ /// </summary>
+ private int _lineNumber;
+
+ /// <summary>
+ /// Column number representing the current code location if available, 0 otherwise.
+ /// </summary>
+ private int _columnNumber;
+
+ /// <summary>
+ /// This flag is set to true when the frame represents a rethrow marker.
+ /// </summary>
+ private bool _isLastFrameFromForeignExceptionStackTrace;
+
+ private void InitMembers()
+ {
+ _method = null;
+ _nativeOffset = OFFSET_UNKNOWN;
+ _ilOffset = OFFSET_UNKNOWN;
+ _fileName = null;
+ _lineNumber = 0;
+ _columnNumber = 0;
+ _isLastFrameFromForeignExceptionStackTrace = false;
+ }
+
+ /// <summary>
+ /// Constructs a StackFrame corresponding to the active stack frame.
+ /// </summary>
+ public StackFrame()
+ {
+ InitMembers();
+ BuildStackFrame(0 + StackTrace.METHODS_TO_SKIP, false);
+ }
+
+ /// <summary>
+ /// Constructs a StackFrame corresponding to the active stack frame.
+ /// </summary>
+ public StackFrame(bool needFileInfo)
+ {
+ InitMembers();
+ BuildStackFrame(0 + StackTrace.METHODS_TO_SKIP, needFileInfo);
+ }
+
+ /// <summary>
+ /// Constructs a StackFrame corresponding to a calling stack frame.
+ /// </summary>
+ public StackFrame(int skipFrames)
+ {
+ InitMembers();
+ BuildStackFrame(skipFrames + StackTrace.METHODS_TO_SKIP, false);
+ }
+
+ /// <summary>
+ /// Constructs a StackFrame corresponding to a calling stack frame.
+ /// </summary>
+ public StackFrame(int skipFrames, bool needFileInfo)
+ {
+ InitMembers();
+ BuildStackFrame(skipFrames + StackTrace.METHODS_TO_SKIP, needFileInfo);
+ }
+
+ /// <summary>
+ /// Constructs a "fake" stack frame, just containing the given file
+ /// name and line number. Use when you don't want to use the
+ /// debugger's line mapping logic.
+ /// </summary>
+ public StackFrame(string fileName, int lineNumber)
+ {
+ InitMembers();
+ BuildStackFrame(StackTrace.METHODS_TO_SKIP, false);
+ _fileName = fileName;
+ _lineNumber = lineNumber;
+ _columnNumber = 0;
+ }
+
+ /// <summary>
+ /// Constructs a "fake" stack frame, just containing the given file
+ /// name, line number and column number. Use when you don't want to
+ /// use the debugger's line mapping logic.
+ /// </summary>
+ public StackFrame(string fileName, int lineNumber, int colNumber)
+ {
+ InitMembers();
+ BuildStackFrame(StackTrace.METHODS_TO_SKIP, false);
+ _fileName = fileName;
+ _lineNumber = lineNumber;
+ _columnNumber = colNumber;
+ }
+
+ /// <summary>
+ /// Constant returned when the native or IL offset is unknown
+ /// </summary>
+ public const int OFFSET_UNKNOWN = -1;
+
+ internal virtual void SetMethodBase(MethodBase mb)
+ {
+ _method = mb;
+ }
+
+ internal virtual void SetOffset(int iOffset)
+ {
+ _nativeOffset = iOffset;
+ }
+
+ internal virtual void SetILOffset(int iOffset)
+ {
+ _ilOffset = iOffset;
+ }
+
+ internal virtual void SetFileName(string strFName)
+ {
+ _fileName = strFName;
+ }
+
+ internal virtual void SetLineNumber(int iLine)
+ {
+ _lineNumber = iLine;
+ }
+
+ internal virtual void SetColumnNumber(int iCol)
+ {
+ _columnNumber = iCol;
+ }
+
+ internal virtual void SetIsLastFrameFromForeignExceptionStackTrace(bool fIsLastFrame)
+ {
+ _isLastFrameFromForeignExceptionStackTrace = fIsLastFrame;
+ }
+
+ internal virtual bool GetIsLastFrameFromForeignExceptionStackTrace()
+ {
+ return _isLastFrameFromForeignExceptionStackTrace;
+ }
+
+ /// <summary>
+ /// Returns the method the frame is executing
+ /// </summary>
+ public virtual MethodBase GetMethod()
+ {
+ return _method;
+ }
+
+ /// <summary>
+ /// Returns the offset from the start of the native (jitted) code for the
+ /// method being executed
+ /// </summary>
+ public virtual int GetNativeOffset()
+ {
+ return _nativeOffset;
+ }
+
+
+ /// <summary>
+ /// Returns the offset from the start of the IL code for the
+ /// method being executed. This offset may be approximate depending
+ /// on whether the jitter is generating debuggable code or not.
+ /// </summary>
+ public virtual int GetILOffset()
+ {
+ return _ilOffset;
+ }
+
+ /// <summary>
+ /// Returns the file name containing the code being executed. This
+ /// information is normally extracted from the debugging symbols
+ /// for the executable.
+ /// </summary>
+ public virtual string GetFileName()
+ {
+ return _fileName;
+ }
+
+ /// <summary>
+ /// Returns the line number in the file containing the code being executed.
+ /// This information is normally extracted from the debugging symbols
+ /// for the executable.
+ /// </summary>
+ public virtual int GetFileLineNumber()
+ {
+ return _lineNumber;
+ }
+
+ /// <summary>
+ /// Returns the column number in the line containing the code being executed.
+ /// This information is normally extracted from the debugging symbols
+ /// for the executable.
+ /// </summary>
+ public virtual int GetFileColumnNumber()
+ {
+ return _columnNumber;
+ }
+
+ /// <summary>
+ /// Builds a readable representation of the stack frame
+ /// </summary>
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder(255);
+ bool includeFileInfoIfAvailable;
+
+ if (_method != null)
+ {
+ sb.Append(_method.Name);
+
+ // deal with the generic portion of the method
+ if (_method is MethodInfo methodInfo && methodInfo.IsGenericMethod)
+ {
+ Type[] typars = methodInfo.GetGenericArguments();
+
+ sb.Append('<');
+ int k = 0;
+ bool fFirstTyParam = true;
+ while (k < typars.Length)
+ {
+ if (fFirstTyParam == false)
+ sb.Append(',');
+ else
+ fFirstTyParam = false;
+
+ sb.Append(typars[k].Name);
+ k++;
+ }
+
+ sb.Append('>');
+ }
+ includeFileInfoIfAvailable = true;
+ }
+ else
+ {
+ includeFileInfoIfAvailable = AppendStackFrameWithoutMethodBase(sb);
+ }
+
+ if (includeFileInfoIfAvailable)
+ {
+ sb.Append(" at offset ");
+ if (_nativeOffset == OFFSET_UNKNOWN)
+ sb.Append("<offset unknown>");
+ else
+ sb.Append(_nativeOffset);
+
+ sb.Append(" in file:line:column ");
+
+ bool useFileName = (_fileName != null);
+
+ if (!useFileName)
+ sb.Append("<filename unknown>");
+ else
+ sb.Append(_fileName);
+ sb.Append(':');
+ sb.Append(_lineNumber);
+ sb.Append(':');
+ sb.Append(_columnNumber);
+ }
+ else
+ {
+ sb.Append("<null>");
+ }
+ sb.Append(Environment.NewLine);
+
+ return sb.ToString();
+ }
+ }
+}