-
-
Notifications
You must be signed in to change notification settings - Fork 203
/
StackFrame.cs
135 lines (111 loc) · 4.64 KB
/
StackFrame.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
namespace Sentry.Internal;
/// <summary>
/// Mockable variant of the Diagnostics.StackFrame.
/// This is necessary to test NativeAOT code that relies on extensions from StackFrameExtensions.
/// </summary>
internal interface IStackFrame
{
StackFrame? Frame { get; }
/// <summary>
/// Returns a pointer to the base address of the native image that this stack frame is executing.
/// </summary>
/// <returns>
/// A pointer to the base address of the native image or System.IntPtr.Zero if you're targeting the .NET Framework.
/// </returns>
public nint GetNativeImageBase();
/// <summary>
/// Gets an interface pointer to the start of the native code for the method that is being executed.
/// </summary>
/// <returns>
/// An interface pointer to the start of the native code for the method that is being
/// executed or System.IntPtr.Zero if you're targeting the .NET Framework.
/// </returns>
public nint GetNativeIP();
/// <summary>
/// Indicates whether the native image is available for the specified stack frame.
/// </summary>
/// <returns>
/// true if a native image is available for this stack frame; otherwise, false.
/// </returns>
public bool HasNativeImage();
/// <summary>
/// Gets the column number in the file that contains the code that is executing.
/// This information is typically extracted from the debugging symbols for the executable.
/// </summary>
/// <returns>
/// The file column number, or 0 (zero) if the file column number cannot be determined.
/// </returns>
public int GetFileColumnNumber();
/// <summary>
/// Gets the line number in the file that contains the code that is executing. This
/// information is typically extracted from the debugging symbols for the executable.
/// </summary>
/// <returns>
/// The file line number, or 0 (zero) if the file line number cannot be determined.
/// </returns>
public int GetFileLineNumber();
/// <summary>
/// Gets the file name that contains the code that is executing. This information
/// is typically extracted from the debugging symbols for the executable.
/// </summary>
/// <returns>
/// The file name, or null if the file name cannot be determined.
/// </returns>
public string? GetFileName();
/// <summary>
/// Gets the offset from the start of the Microsoft intermediate language (MSIL)
/// code for the method that is executing. This offset might be an approximation
/// depending on whether or not the just-in-time (JIT) compiler is generating debugging
/// code. The generation of this debugging information is controlled by the System.Diagnostics.DebuggableAttribute.
/// </summary>
/// <returns>
/// The offset from the start of the MSIL code for the method that is executing.
/// </returns>
public int GetILOffset();
/// <summary>
/// Gets the method in which the frame is executing.
/// </summary>
/// <returns>
/// The method in which the frame is executing.
/// </returns>
public MethodBase? GetMethod();
/// <summary>
/// Builds a readable representation of the stack trace.
/// </summary>
/// <returns>
/// A readable representation of the stack trace.
/// </returns>
public string ToString();
}
internal class RealStackFrame : IStackFrame
{
private readonly StackFrame _frame;
public RealStackFrame(StackFrame frame)
{
_frame = frame;
}
public StackFrame? Frame => _frame;
public override string ToString() => _frame.ToString();
public int GetFileColumnNumber() => _frame.GetFileColumnNumber();
public int GetFileLineNumber() => _frame.GetFileLineNumber();
public string? GetFileName() => _frame.GetFileName();
public int GetILOffset() => _frame.GetILOffset();
[UnconditionalSuppressMessage("Trimming",
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
Justification = AotHelper.SuppressionJustification)]
public MethodBase? GetMethod()
{
#pragma warning disable 0162 // Unreachable code on old .NET frameworks
return AotHelper.IsNativeAot ? null : _frame.GetMethod();
#pragma warning restore 0162
}
#if NET5_0_OR_GREATER
public nint GetNativeImageBase() => _frame.GetNativeImageBase();
public nint GetNativeIP() => _frame.GetNativeIP();
public bool HasNativeImage() => _frame.HasNativeImage();
#else
public nint GetNativeImageBase() => default;
public nint GetNativeIP() => default;
public bool HasNativeImage() => false;
#endif
}