Welcome to mirror list, hosted at ThFree Co, Russian Federation.

StackFrame.cs « System.Diagnostics « corlib « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: f27256fbde5af09ba81de47d87da9db284e48a31 (plain)
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
//
// System.Diagnostics.StackFrame.cs
//
// Author:
//      Alexander Klyubin (klyubin@aqris.com)
//      Dietmar Maurer (dietmar@ximian.com)
//
// (C) 2001
//

using System;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace System.Diagnostics {
        /// <summary>
        ///   Stack frame.
        /// </summary>

	[Serializable]
        public class StackFrame {
                /// <value>
                ///   Constant returned when the native or IL offset is unknown.
                /// </value>
                public const int OFFSET_UNKNOWN = -1;
                
                /// <value>
                ///   Offset from the start of the IL code for the method
                ///   being executed.
                /// </value>
                private int ilOffset = OFFSET_UNKNOWN;
                
                /// <value>
                ///   Offset from the start of the native code for the method
                ///   being executed.
                /// </value>
                private int nativeOffset = OFFSET_UNKNOWN;

                /// <value>
                ///   Method associated with this stack frame.
                /// </value>
                private MethodBase methodBase;
                
                /// <value>
                ///   File name.
                /// </value>
                private string fileName;
                
                /// <value>
                ///   Line number.
                /// </value>
                private int lineNumber;
                
                /// <value>
                ///   Column number.
                /// </value>
                private int columnNumber;

		[MethodImplAttribute(MethodImplOptions.InternalCall)]
		extern static bool get_frame_info (int skip, bool needFileInfo, out MethodBase method,
						   out int iloffset, out int native_offset,
						   out string file, out int line, out int column);

                /// <summary>
                ///   Initializes a new StackFrame object corresponding to the
                ///   active stack frame.
                /// </summary>
                public StackFrame() {
			get_frame_info (2, false, out methodBase, out ilOffset,
					out nativeOffset, out fileName, out lineNumber,
					out columnNumber);			
                }
                
                /// <summary>
                ///   Initializes a new StackFrame object corresponding to the
                ///   active stack frame.
                /// </summary>
                /// <param name="needFileInfo">
                ///   TODO:
                /// </param>
                public StackFrame(bool needFileInfo) : this() {
			get_frame_info (2, needFileInfo, out methodBase, out ilOffset,
					out nativeOffset, out fileName, out lineNumber,
					out columnNumber);			
                }
                
                /// <summary>
                ///   Initializes a new StackFrame object corresponding to the
                ///   active stack frame.
                /// </summary>
                /// <param name="skipFrames">
                ///   The number of frames up the stack to skip.
                /// </param>
                public StackFrame(int skipFrames) {
			get_frame_info (skipFrames + 2, false, out methodBase, out ilOffset,
					out nativeOffset, out fileName, out lineNumber,
					out columnNumber);			
                }
                
                /// <summary>
                ///   Initializes a new StackFrame object corresponding to the
                ///   active stack frame.
                /// </summary>
                /// <param name="skipFrames">
                ///   The number of frames up the stack to skip.
                /// </param>
                /// <param name="needFileInfo">
                ///   TODO:
                /// </param>
                public StackFrame(int skipFrames, bool needFileInfo) {
			get_frame_info (skipFrames + 2, needFileInfo, out methodBase, out ilOffset,
					out nativeOffset, out fileName, out lineNumber,
					out columnNumber);
                }
                
                /// <summary>
                ///   Constructs a fake stack frame that just contains the
                ///   given file name and line number. Use this constructor
                ///   when you do not want to use the debugger's line mapping
                ///   logic.
                /// </summary>
                /// <param name="fileName">
                ///   The given file name.
                /// </param>
                /// <param name="lineNumber">
                ///   The line number in the specified file.
                /// </param>
                public StackFrame(string fileName, int lineNumber)
                : this (fileName, lineNumber, 0) {}
                
                /// <summary>
                ///   Constructs a fake stack frame that just contains the
                ///   given file name and line number. Use this constructor
                ///   when you do not want to use the debugger's line mapping
                ///   logic.
                /// </summary>
                /// <param name="fileName">
                ///   The given file name.
                /// </param>
                /// <param name="lineNumber">
                ///   The line number in the specified file.
                /// </param>
                /// <param name="colNumber">
                ///   The column number in the specified file.
                /// </param>
                public StackFrame(string fileName,
                                  int lineNumber,
                                  int colNumber) {
                        this.methodBase = null;
                        this.fileName = fileName;
                        this.lineNumber = lineNumber;
                        this.columnNumber = colNumber;
                }
                                  
                              
                /// <summary>
                ///   Gets the line number in the file containing the code
                ///   being executed. This information is typically extracted
                ///   from the debugging symbols for the executable.
                /// </summary>
                /// <returns>
                ///   The file line number or zero if it cannot be determined.
                /// </returns>
                public virtual int GetFileLineNumber()
                {
                        return lineNumber;
                }
                
                /// <summary>
                ///   Gets the column number in the file containing the code
                ///   being executed. This information is typically extracted
                ///   from the debugging symbols for the executable.
                /// </summary>
                /// <returns>
                ///   The file column number or zero if it cannot be determined.
                /// </returns>
                public virtual int GetFileColumnNumber()
                {
                        return columnNumber;
                }
                
                /// <summary>
                ///   Gets the file name containing the code being executed.
                ///   This information is typically extracted from the
                ///   debugging symbols for the executable.
                /// </summary>
                /// <returns>
                ///   The file name or null if it cannot be determined.
                /// </returns> 
                public virtual string GetFileName()
                {
                        return fileName;
                }
                
                /// <summary>
                ///   Gets the offset from the start of the IL code for the
                ///   method being executed. This offset may be approximate
                ///   depending on whether the JIT compiler is generating
                ///   debugging code or not.
                /// </summary>
                /// <returns>
                ///   The offset from the start of the IL code for the method
                ///   being executed.
                /// </returns>
                public virtual int GetILOffset()
                {
                        return ilOffset;
                }
                
                /// <summary>
                ///   Gets the method in which the frame is executing.
                /// </summary>
                /// <returns>
                ///   The method the frame is executing in.
                /// </returns>
                public virtual MethodBase GetMethod()
                {
                        return methodBase;
                }
                
                /// <summary>
                ///   Gets the offset from the start of the native
                ///   (JIT-compiled) code for the method being executed.
                /// </summary>
                /// <returns>
                ///   The offset from the start of the native (JIT-compiled)
                ///   code or the method being executed.
                /// </returns>
                public virtual int GetNativeOffset()
                {
                        return nativeOffset;                        
                }
                
                /// <summary>
                ///   Builds a readable representation of the stack frame.
                /// </summary>
                /// <returns>
                ///   A readable representation of the stack frame.
                /// </returns>
                public override string ToString() {
                        string methodNameString =
                                (GetMethod() == null)
                                        ? "<unknown method>"
                                          : GetMethod().Name;
                        string offsetString =
                                (GetILOffset() == OFFSET_UNKNOWN)
                                        ? "<unknown offset>"
                                          : "offset " + GetILOffset();
                        string fileNameString =
                                (GetFileName() == null)
                                        ? "<filename unknown>" : GetFileName();
                        return methodNameString + " at " + offsetString
                                + " in file:line:column " + fileNameString
                                + ":" + GetFileLineNumber()
                                + ":" + GetFileColumnNumber();
                }
                
                public override bool Equals(Object obj) {
                        if ((obj == null) || (!(obj is StackFrame))) {
                                return false;
                        }
                        
                        StackFrame rhs = (StackFrame) obj;
                        
                        if (!ObjectsEqual(GetMethod(), rhs.GetMethod())) {
                                return false;
                        }
                        
                        if (!ObjectsEqual(GetFileName(), rhs.GetFileName())) {
                                return false;
                        }
                        
                        if (GetFileLineNumber() != rhs.GetFileLineNumber()) {
                                return false;
                        }
                        
                        if (GetFileColumnNumber() != rhs.GetFileColumnNumber()) {
                                return false;
                        }
                        
                        if (GetILOffset() != rhs.GetILOffset()) {
                                return false;
                        }
                        
                        if (GetNativeOffset() != rhs.GetNativeOffset()) {
                                return false;
                        }
                        
                        return true;
                        
                }
                
                public override int GetHashCode() {
                        return GetFileLineNumber();
                }
                
                /// <summary>
                ///   Checks whether two objects are equal.
                ///   The objects are assumed equal if and only if either
                ///   both of the references are <code>null</code> or they
                ///   equal via <code>Equals</code> method.
                /// </summary>
                /// <param name="obj1">
                ///   First object.
                /// </param>
                /// <param name="obj2">
                ///   Second object.
                /// </param>
                /// <returns>
                ///   <code>true</code> if the two objects are equal,
                ///   </code>false</code> otherwise.
                /// </returns>
                private static bool ObjectsEqual(Object obj1, Object obj2) {
                        if (obj1 == null) {
                                return (obj2 == null);
                        } else {
                                return obj1.Equals(obj2);
                        }
                }
         }
}