2 using System.Text.RegularExpressions;
3 using System.Globalization;
9 static Regex regex = new Regex (@"\w*at (?<Method>.+) *(\[0x(?<IL>.+)\]|<0x.+ \+ 0x(?<NativeOffset>.+)>( (?<MethodIndex>\d+)|)) in <filename unknown>:0");
11 public readonly string TypeFullName;
12 public readonly string MethodSignature;
13 public readonly int Offset;
14 public readonly bool IsILOffset;
15 public readonly uint MethodIndex;
16 public readonly string Line;
18 public readonly bool IsValid;
20 public string File { get; private set; }
21 public int LineNumber { get; private set; }
23 private StackFrameData (string line, string typeFullName, string methodSig, int offset, bool isILOffset, uint methodIndex)
28 TypeFullName = typeFullName;
29 MethodSignature = methodSig;
31 IsILOffset = isILOffset;
32 MethodIndex = methodIndex;
37 private StackFrameData (string line)
44 public static bool TryParse (string line, out StackFrameData stackFrame)
48 var match = regex.Match (line);
50 if (line.Trim ().StartsWith ("at ", StringComparison.InvariantCulture)) {
51 stackFrame = new StackFrameData (line);
57 string typeFullName, methodSignature;
58 var methodStr = match.Groups ["Method"].Value.Trim ();
59 if (!ExtractSignatures (methodStr, out typeFullName, out methodSignature))
62 var isILOffset = !string.IsNullOrEmpty (match.Groups ["IL"].Value);
63 var offsetVarName = (isILOffset)? "IL" : "NativeOffset";
64 var offset = int.Parse (match.Groups [offsetVarName].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
66 uint methodIndex = 0xffffff;
67 if (!string.IsNullOrEmpty (match.Groups ["MethodIndex"].Value))
68 methodIndex = uint.Parse (match.Groups ["MethodIndex"].Value, CultureInfo.InvariantCulture);
70 stackFrame = new StackFrameData (line, typeFullName, methodSignature, offset, isILOffset, methodIndex);
75 static bool ExtractSignatures (string str, out string typeFullName, out string methodSignature)
77 var methodNameEnd = str.IndexOf ('(');
78 if (methodNameEnd == -1) {
79 typeFullName = methodSignature = null;
83 var typeNameEnd = str.LastIndexOf ('.', methodNameEnd);
84 if (typeNameEnd == -1) {
85 typeFullName = methodSignature = null;
89 // Adjustment for Type..ctor ()
90 if (typeNameEnd > 0 && str [typeNameEnd - 1] == '.') {
94 typeFullName = str.Substring (0, typeNameEnd);
95 // Remove generic parameters
96 typeFullName = Regex.Replace (typeFullName, @"\[[^\[\]]*\]", "");
98 methodSignature = str.Substring (typeNameEnd + 1);
103 internal void SetLocation (string file, int lineNumber)
106 LineNumber = lineNumber;
109 public override string ToString () {
110 if (Line.Contains ("<filename unknown>:0") && LineNumber != -1)
111 return Line.Replace ("<filename unknown>:0", string.Format ("{0}:{1}", File, LineNumber));