Moving common logic of StackFrame into shared (dotnet/coreclr#18134)
authorMaryam Ariyan <maryam.ariyan@microsoft.com>
Tue, 29 May 2018 23:13:13 +0000 (16:13 -0700)
committerJan Kotas <jkotas@microsoft.com>
Tue, 29 May 2018 23:13:13 +0000 (16:13 -0700)
Related to: dotnet/coreclr#9474

Commit migrated from https://github.com/dotnet/coreclr/commit/98c22a44ceab4f54607df65ef200e7bf7acb6145

src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj
src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs [new file with mode: 0644]
src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Stackframe.cs [deleted file]
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs [new file with mode: 0644]

index a555265..1932ebc 100644 (file)
     <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" />
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs
new file mode 100644 (file)
index 0000000..a08496a
--- /dev/null
@@ -0,0 +1,51 @@
+// 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;
+    }
+}
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Stackframe.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Stackframe.cs
deleted file mode 100644 (file)
index 884188d..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-// 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);
-                }
-            }
-        }
-    }
-}
index e292908..8c7464f 100644 (file)
     <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" />
diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs
new file mode 100644 (file)
index 0000000..22c9b83
--- /dev/null
@@ -0,0 +1,302 @@
+// 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();
+        }
+    }
+}