The Labs \ Source Viewer \ SSCLI \ System.Diagnostics \ StackFrame

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System.Diagnostics
  16. {
  17.    
  18.     using System.Text;
  19.     using System;
  20.     using System.IO;
  21.     using System.Reflection;
  22.     using System.Security.Permissions;
  23.    
  24.     // There is no good reason for the methods of this class to be virtual.
  25.     // In order to ensure trusted code can trust the data it gets from a
  26.     // StackTrace, we use an InheritanceDemand to prevent partially-trusted
  27.     // subclasses.
  28.     [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
  29.     [Serializable()]
  30.     [System.Runtime.InteropServices.ComVisible(true)]
  31.     public class StackFrame
  32.     {
  33.         private MethodBase method;
  34.         private int offset;
  35.         private int ILOffset;
  36.         private string strFileName;
  37.         private int iLineNumber;
  38.         private int iColumnNumber;
  39.        
  40.         internal void InitMembers()
  41.         {
  42.             method = null;
  43.             offset = OFFSET_UNKNOWN;
  44.             ILOffset = OFFSET_UNKNOWN;
  45.             strFileName = null;
  46.             iLineNumber = 0;
  47.             iColumnNumber = 0;
  48.         }
  49.        
  50.         // Constructs a StackFrame corresponding to the active stack frame.
  51.         public StackFrame()
  52.         {
  53.             InitMembers();
  54.             BuildStackFrame(0 + StackTrace.METHODS_TO_SKIP, false);
  55.             // iSkipFrames=0
  56.         }
  57.        
  58.         // Constructs a StackFrame corresponding to the active stack frame.
  59.         public StackFrame(bool fNeedFileInfo)
  60.         {
  61.             InitMembers();
  62.             BuildStackFrame(0 + StackTrace.METHODS_TO_SKIP, fNeedFileInfo);
  63.             // iSkipFrames=0
  64.         }
  65.        
  66.         // Constructs a StackFrame corresponding to a calling stack frame.
  67.         //
  68.         public StackFrame(int skipFrames)
  69.         {
  70.             InitMembers();
  71.             BuildStackFrame(skipFrames + StackTrace.METHODS_TO_SKIP, false);
  72.         }
  73.        
  74.         // Constructs a StackFrame corresponding to a calling stack frame.
  75.         //
  76.         public StackFrame(int skipFrames, bool fNeedFileInfo)
  77.         {
  78.             InitMembers();
  79.             BuildStackFrame(skipFrames + StackTrace.METHODS_TO_SKIP, fNeedFileInfo);
  80.         }
  81.        
  82.        
  83.         // Called from the class "StackTrace"
  84.         //
  85.         internal StackFrame(bool DummyFlag1, bool DummyFlag2)
  86.         {
  87.             InitMembers();
  88.         }
  89.        
  90.         // Constructs a "fake" stack frame, just containing the given file
  91.         // name and line number. Use when you don't want to use the
  92.         // debugger's line mapping logic.
  93.         //
  94.         public StackFrame(string fileName, int lineNumber)
  95.         {
  96.             InitMembers();
  97.             BuildStackFrame(StackTrace.METHODS_TO_SKIP, false);
  98.             strFileName = fileName;
  99.             iLineNumber = lineNumber;
  100.             iColumnNumber = 0;
  101.         }
  102.        
  103.        
  104.         // Constructs a "fake" stack frame, just containing the given file
  105.         // name, line number and column number. Use when you don't want to
  106.         // use the debugger's line mapping logic.
  107.         //
  108.         public StackFrame(string fileName, int lineNumber, int colNumber)
  109.         {
  110.             InitMembers();
  111.             BuildStackFrame(StackTrace.METHODS_TO_SKIP, false);
  112.             strFileName = fileName;
  113.             iLineNumber = lineNumber;
  114.             iColumnNumber = colNumber;
  115.         }
  116.        
  117.        
  118.         // Constant returned when the native or IL offset is unknown
  119.         public const int OFFSET_UNKNOWN = -1;
  120.        
  121.        
  122.         internal virtual void SetMethodBase(MethodBase mb)
  123.         {
  124.             method = mb;
  125.         }
  126.        
  127.         internal virtual void SetOffset(int iOffset)
  128.         {
  129.             offset = iOffset;
  130.         }
  131.        
  132.         internal virtual void SetILOffset(int iOffset)
  133.         {
  134.             ILOffset = iOffset;
  135.         }
  136.        
  137.         internal virtual void SetFileName(string strFName)
  138.         {
  139.             strFileName = strFName;
  140.         }
  141.        
  142.         internal virtual void SetLineNumber(int iLine)
  143.         {
  144.             iLineNumber = iLine;
  145.         }
  146.        
  147.         internal virtual void SetColumnNumber(int iCol)
  148.         {
  149.             iColumnNumber = iCol;
  150.         }
  151.        
  152.        
  153.         // Returns the method the frame is executing
  154.         //
  155.         public virtual MethodBase GetMethod()
  156.         {
  157.             return method;
  158.         }
  159.        
  160.         // Returns the offset from the start of the native (jitted) code for the
  161.         // method being executed
  162.         //
  163.         public virtual int GetNativeOffset()
  164.         {
  165.             return offset;
  166.         }
  167.        
  168.        
  169.         // Returns the offset from the start of the IL code for the
  170.         // method being executed. This offset may be approximate depending
  171.         // on whether the jitter is generating debuggable code or not.
  172.         //
  173.         public virtual int GetILOffset()
  174.         {
  175.             return ILOffset;
  176.         }
  177.        
  178.         // Returns the file name containing the code being executed. This
  179.         // information is normally extracted from the debugging symbols
  180.         // for the executable.
  181.         //
  182.         public virtual string GetFileName()
  183.         {
  184.             if (strFileName != null) {
  185.                 // This isn't really correct, but we don't have
  186.                 // a permission that protects discovery of potentially
  187.                 // local urls so we'll use this.
  188.                
  189.                 FileIOPermission perm = new FileIOPermission(PermissionState.None);
  190.                 perm.AllFiles = FileIOPermissionAccess.PathDiscovery;
  191.                 perm.Demand();
  192.             }
  193.            
  194.             return strFileName;
  195.         }
  196.        
  197.         // Returns the line number in the file containing the code being executed.
  198.         // This information is normally extracted from the debugging symbols
  199.         // for the executable.
  200.         //
  201.         public virtual int GetFileLineNumber()
  202.         {
  203.             return iLineNumber;
  204.         }
  205.        
  206.         // Returns the column number in the line containing the code being executed.
  207.         // This information is normally extracted from the debugging symbols
  208.         // for the executable.
  209.         //
  210.         public virtual int GetFileColumnNumber()
  211.         {
  212.             return iColumnNumber;
  213.         }
  214.        
  215.        
  216.         // Builds a readable representation of the stack frame
  217.         //
  218.         public override string ToString()
  219.         {
  220.             StringBuilder sb = new StringBuilder(255);
  221.            
  222.             if (method != null) {
  223.                 sb.Append(method.Name);
  224.                
  225.                 // deal with the generic portion of the method
  226.                 if (method is MethodInfo && ((MethodInfo)method).IsGenericMethod) {
  227.                     Type[] typars = ((MethodInfo)method).GetGenericArguments();
  228.                    
  229.                     sb.Append("<");
  230.                     int k = 0;
  231.                     bool fFirstTyParam = true;
  232.                     while (k < typars.Length) {
  233.                         if (fFirstTyParam == false)
  234.                             sb.Append(",");
  235.                         else
  236.                             fFirstTyParam = false;
  237.                        
  238.                         sb.Append(typars[k].Name);
  239.                         k++;
  240.                     }
  241.                    
  242.                     sb.Append(">");
  243.                 }
  244.                
  245.                 sb.Append(" at offset ");
  246.                 if (offset == OFFSET_UNKNOWN)
  247.                     sb.Append("<offset unknown>");
  248.                 else
  249.                     sb.Append(offset);
  250.                
  251.                 sb.Append(" in file:line:column ");
  252.                
  253.                 bool useFileName = (strFileName != null);
  254.                
  255.                 if (useFileName) {
  256.                     try {
  257.                         // This isn't really correct, but we don't have
  258.                         // a permission that protects discovery of potentially
  259.                         // local urls so we'll use this.
  260.                        
  261.                         FileIOPermission perm = new FileIOPermission(PermissionState.None);
  262.                         perm.AllFiles = FileIOPermissionAccess.PathDiscovery;
  263.                         perm.Demand();
  264.                     }
  265.                     catch (System.Security.SecurityException) {
  266.                         useFileName = false;
  267.                     }
  268.                 }
  269.                
  270.                 if (!useFileName)
  271.                     sb.Append("<filename unknown>");
  272.                 else
  273.                     sb.Append(strFileName);
  274.                 sb.Append(":");
  275.                 sb.Append(iLineNumber);
  276.                 sb.Append(":");
  277.                 sb.Append(iColumnNumber);
  278.             }
  279.             else {
  280.                 sb.Append("<null>");
  281.             }
  282.             sb.Append(Environment.NewLine);
  283.            
  284.             return sb.ToString();
  285.         }
  286.        
  287.        
  288.         private void BuildStackFrame(int skipFrames, bool fNeedFileInfo)
  289.         {
  290.             StackFrameHelper StackF = new StackFrameHelper(fNeedFileInfo, null);
  291.            
  292.             StackTrace.GetStackFramesInternal(StackF, 0, null);
  293.            
  294.             int iNumOfFrames = StackF.GetNumberOfFrames();
  295.            
  296.             skipFrames += StackTrace.CalculateFramesToSkip(StackF, iNumOfFrames);
  297.            
  298.             if ((iNumOfFrames - skipFrames) > 0) {
  299.                 method = StackF.GetMethodBase(skipFrames);
  300.                 offset = StackF.GetOffset(skipFrames);
  301.                 ILOffset = StackF.GetILOffset(skipFrames);
  302.                 if (fNeedFileInfo) {
  303.                     strFileName = StackF.GetFilename(skipFrames);
  304.                     iLineNumber = StackF.GetLineNumber(skipFrames);
  305.                     iColumnNumber = StackF.GetColumnNumber(skipFrames);
  306.                 }
  307.             }
  308.         }
  309.     }
  310. }

Developer Fusion