ed5134709cd774a025ee43a933407712df6d3d55
[mono.git] / mcs / tools / mono-symbolicate / StackFrameData.cs
1 using System;
2 using System.Text.RegularExpressions;
3 using System.Globalization;
4
5 namespace Mono
6 {
7         class StackFrameData
8         {
9                 static Regex regex = new Regex (@"\w*at (?<Method>.+) *(\[0x(?<IL>.+)\]|<0x.+ \+ 0x(?<NativeOffset>.+)>( (?<MethodIndex>\d+)|)) in <filename unknown>:0");
10
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;
17
18                 public readonly bool IsValid;
19
20                 public string File { get; private set; }
21                 public int LineNumber { get; private set; }
22
23                 private StackFrameData (string line, string typeFullName, string methodSig, int offset, bool isILOffset, uint methodIndex)
24                 {
25                         LineNumber = -1;
26
27                         Line = line;
28                         TypeFullName = typeFullName;
29                         MethodSignature = methodSig;
30                         Offset = offset;
31                         IsILOffset = isILOffset;
32                         MethodIndex = methodIndex;
33
34                         IsValid = true;
35                 }
36
37                 private StackFrameData (string line)
38                 {
39                         LineNumber = -1;
40
41                         Line = line;
42                 }
43
44                 public static bool TryParse (string line, out StackFrameData stackFrame)
45                 {
46                         stackFrame = null;
47
48                         var match = regex.Match (line);
49                         if (!match.Success) {
50                                 if (line.Trim ().StartsWith ("at ", StringComparison.InvariantCulture)) {
51                                         stackFrame = new StackFrameData (line);
52                                         return true;
53                                 }
54                                 return false;
55                         }
56
57                         string typeFullName, methodSignature;
58                         var methodStr = match.Groups ["Method"].Value.Trim ();
59                         if (!ExtractSignatures (methodStr, out typeFullName, out methodSignature))
60                                 return false;
61
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);
65
66                         uint methodIndex = 0xffffff;
67                         if (!string.IsNullOrEmpty (match.Groups ["MethodIndex"].Value))
68                                 methodIndex = uint.Parse (match.Groups ["MethodIndex"].Value, CultureInfo.InvariantCulture);
69
70                         stackFrame = new StackFrameData (line, typeFullName, methodSignature, offset, isILOffset, methodIndex);
71
72                         return true;
73                 }
74
75                 static bool ExtractSignatures (string str, out string typeFullName, out string methodSignature)
76                 {
77                         var methodNameEnd = str.IndexOf ('(');
78                         if (methodNameEnd == -1) {
79                                 typeFullName = methodSignature = null;
80                                 return false;
81                         }
82
83                         var typeNameEnd = str.LastIndexOf ('.', methodNameEnd);
84                         if (typeNameEnd == -1) {
85                                 typeFullName = methodSignature = null;
86                                 return false;
87                         }
88
89                         // Adjustment for Type..ctor ()
90                         if (typeNameEnd > 0 && str [typeNameEnd - 1] == '.') {
91                                 --typeNameEnd;
92                         }
93
94                         typeFullName = str.Substring (0, typeNameEnd);
95                         // Remove generic parameters
96                         typeFullName = Regex.Replace (typeFullName, @"\[[^\[\]]*\]", "");
97
98                         methodSignature = str.Substring (typeNameEnd + 1);
99
100                         return true;
101                 }
102
103                 internal void SetLocation (string file, int lineNumber)
104                 {
105                         File = file;
106                         LineNumber = lineNumber;
107                 }
108
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));
112
113                         return Line;
114                 }
115         }
116 }