2010-05-27 Jb Evain <jbevain@novell.com>
[mcs.git] / class / corlib / System.Diagnostics / StackTrace.cs
blobe8ec9fb650d7bbe9cefd9f2b6a0d31efdcc14fcb
1 //
2 // System.Diagnostics.StackTrace.cs
3 //
4 // Author:
5 // Alexander Klyubin (klyubin@aqris.com)
6 // Dietmar Maurer (dietmar@ximian.com)
7 //
8 // (C) 2001
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
32 using System.Globalization;
33 using System.Reflection;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.InteropServices;
36 using System.Security;
37 using System.Security.Permissions;
38 using System.Text;
39 using System.Threading;
41 namespace System.Diagnostics {
43 [Serializable]
44 [ComVisible (true)]
45 [MonoTODO ("Serialized objects are not compatible with .NET")]
46 public class StackTrace {
48 public const int METHODS_TO_SKIP = 0;
50 private StackFrame[] frames;
51 private bool debug_info;
53 public StackTrace ()
55 init_frames (METHODS_TO_SKIP, false);
58 public StackTrace (bool fNeedFileInfo)
60 init_frames (METHODS_TO_SKIP, fNeedFileInfo);
63 public StackTrace (int skipFrames)
65 init_frames (skipFrames, false);
68 public StackTrace (int skipFrames, bool fNeedFileInfo)
70 init_frames (skipFrames, fNeedFileInfo);
73 void init_frames (int skipFrames, bool fNeedFileInfo)
75 if (skipFrames < 0)
76 throw new ArgumentOutOfRangeException ("< 0", "skipFrames");
78 StackFrame sf;
79 ArrayList al = new ArrayList ();
81 skipFrames += 2;
83 while ((sf = new StackFrame (skipFrames, fNeedFileInfo)) != null &&
84 sf.GetMethod () != null) {
86 al.Add (sf);
87 skipFrames++;
90 debug_info = fNeedFileInfo;
91 frames = (StackFrame [])al.ToArray (typeof (StackFrame));
94 [MethodImplAttribute(MethodImplOptions.InternalCall)]
95 extern static StackFrame [] get_trace (Exception e, int skipFrames, bool fNeedFileInfo);
97 public StackTrace (Exception e)
98 : this (e, METHODS_TO_SKIP, false)
102 public StackTrace (Exception e, bool fNeedFileInfo)
103 : this (e, METHODS_TO_SKIP, fNeedFileInfo)
107 public StackTrace (Exception e, int skipFrames)
108 : this (e, skipFrames, false)
112 public StackTrace (Exception e, int skipFrames, bool fNeedFileInfo)
113 : this (e, skipFrames, fNeedFileInfo, false)
117 internal StackTrace (Exception e, int skipFrames, bool fNeedFileInfo, bool returnNativeFrames)
119 if (e == null)
120 throw new ArgumentNullException ("e");
121 if (skipFrames < 0)
122 throw new ArgumentOutOfRangeException ("< 0", "skipFrames");
124 frames = get_trace (e, skipFrames, fNeedFileInfo);
126 if (!returnNativeFrames) {
127 bool resize = false;
128 for (int i = 0; i < frames.Length; ++i)
129 if (frames [i].GetMethod () == null)
130 resize = true;
132 if (resize) {
133 ArrayList al = new ArrayList ();
135 for (int i = 0; i < frames.Length; ++i)
136 if (frames [i].GetMethod () != null)
137 al.Add (frames [i]);
139 frames = (StackFrame [])al.ToArray (typeof (StackFrame));
144 public StackTrace (StackFrame frame)
146 this.frames = new StackFrame [1];
147 this.frames [0] = frame;
150 [MonoLimitation ("Not possible to create StackTraces from other threads")]
151 public StackTrace (Thread targetThread, bool needFileInfo)
153 if (targetThread == Thread.CurrentThread){
154 init_frames (METHODS_TO_SKIP, needFileInfo);
155 return;
158 throw new NotImplementedException ();
161 public virtual int FrameCount {
162 get {
163 return (frames == null) ? 0 : frames.Length;
167 public virtual StackFrame GetFrame (int index)
169 if ((index < 0) || (index >= FrameCount)) {
170 return null;
173 return frames [index];
176 [ComVisibleAttribute (false)]
177 public virtual StackFrame[] GetFrames ()
179 return frames;
182 public override string ToString ()
184 string newline = String.Format ("{0} {1} ", Environment.NewLine, Locale.GetText ("at"));
185 string unknown = Locale.GetText ("<unknown method>");
186 string debuginfo = Locale.GetText (" in {0}:line {1}");
187 StringBuilder sb = new StringBuilder ();
188 for (int i = 0; i < FrameCount; i++) {
189 StackFrame frame = GetFrame (i);
190 if (i > 0)
191 sb.Append (newline);
192 else
193 sb.AppendFormat (" {0} ", Locale.GetText ("at"));
194 MethodBase method = frame.GetMethod ();
195 if (method != null) {
196 // Method information available
197 sb.AppendFormat ("{0}.{1}", method.DeclaringType.FullName, method.Name);
198 /* Append parameter information */
199 sb.Append ("(");
200 ParameterInfo[] p = method.GetParameters ();
201 for (int j = 0; j < p.Length; ++j) {
202 if (j > 0)
203 sb.Append (", ");
204 Type pt = p[j].ParameterType;
205 bool byref = pt.IsByRef;
206 if (byref)
207 pt = pt.GetElementType ();
208 if (pt.IsClass && pt.Namespace != String.Empty) {
209 sb.Append (pt.Namespace);
210 sb.Append (".");
212 sb.Append (pt.Name);
213 if (byref)
214 sb.Append (" ByRef");
215 sb.AppendFormat (" {0}", p [j].Name);
217 sb.Append (")");
219 else {
220 // Method information not available
221 sb.Append (unknown);
224 if (debug_info) {
225 // we were asked for debugging informations
226 // but that doesn't mean we have the debug information available
227 string fname = frame.GetSecureFileName ();
228 if (fname != "<filename unknown>")
229 sb.AppendFormat (debuginfo, fname, frame.GetFileLineNumber ());
232 return sb.ToString ();