[mono-symbolicate] Fixes last stacktrace issue.
[mono.git] / mcs / tools / mono-symbolicate / symbolicate.cs
1 using System;
2 using System.IO;
3 using System.Text;
4 using System.Linq;
5 using System.Collections.Generic;
6 using System.Globalization;
7
8 namespace Mono
9 {
10         public class Symbolicate
11         {
12                 public static int Main (String[] args)
13                 {
14                         if (args.Length != 2 && (args[0] == "store-symbols" && args.Length < 3)) {
15                                 Console.Error.WriteLine ("Usage: symbolicate <msym dir> <input file>");
16                                 Console.Error.WriteLine ("       symbolicate store-symbols <msym dir> [<dir>]+");
17                                 return 1;
18                         }
19
20                         if (args[0] == "store-symbols") {
21                                 var msymDir = args[1];
22                                 var lookupDirs = args.Skip (1).ToArray ();
23
24                                 var symbolManager = new SymbolManager (msymDir);
25
26                                 symbolManager.StoreSymbols (lookupDirs);
27
28                         } else {
29                                 var msymDir = args [0];
30                                 var inputFile = args [1];
31
32                                 var symbolManager = new SymbolManager (msymDir);
33
34                                 using (StreamReader r = new StreamReader (inputFile)) {
35                                         var sb = Process (r, symbolManager);
36                                         Console.Write (sb.ToString ());
37                                 }
38                         }
39
40                         return 0;
41                 }
42
43                 public static StringBuilder Process (StreamReader reader, SymbolManager symbolManager)
44                 {
45                         List<StackFrameData> stackFrames = new List<StackFrameData>();
46                         List<StackTraceMetadata> metadata = new List<StackTraceMetadata>();
47                         StringBuilder sb = new StringBuilder ();
48                         bool linesEnded = false;
49
50                         for (var line = reader.ReadLine (); line != null; line = reader.ReadLine ()) {
51                                 StackFrameData sfData;
52                                 if (!linesEnded && StackFrameData.TryParse (line, out sfData)) {
53                                         stackFrames.Add (sfData);
54                                         continue;
55                                 }
56
57                                 if (stackFrames.Count > 0) {
58                                         linesEnded = true;
59
60                                         StackTraceMetadata stMetadata;
61                                         if (StackTraceMetadata.TryParse (line, out stMetadata)) {
62                                                 metadata.Add (stMetadata);
63                                                 continue;
64                                         }
65
66                                         DumpStackTrace (symbolManager, sb, stackFrames, metadata);
67                 
68                                         // Clear lists for next stack trace
69                                         stackFrames.Clear ();
70                                         metadata.Clear ();
71                                 }
72
73                                 linesEnded = false;
74
75                                 // Append last line
76                                 sb.AppendLine (line);
77                         }
78
79                         if (stackFrames.Count > 0)
80                                 DumpStackTrace (symbolManager, sb, stackFrames, metadata);
81
82                         return sb;
83                 }
84
85                 private static void DumpStackTrace (SymbolManager symbolManager, StringBuilder sb, List<StackFrameData> stackFrames, List<StackTraceMetadata> metadata)
86                 {
87                         string aotid = null;
88                         var aotidMetadata = metadata.FirstOrDefault ( m => m.Id == "AOTID" );
89                         if (aotidMetadata != null)
90                                 aotid = aotidMetadata.Value;
91
92                         var linesMvid = ProcessLinesMVID (metadata);
93                         var lineNumber = 0;
94                         foreach (var sfData in stackFrames) {
95                                 string mvid = null;
96                                 if (linesMvid.ContainsKey (lineNumber))
97                                         mvid = linesMvid [lineNumber++];
98
99                                 symbolManager.TryResolveLocation (sfData, mvid, aotid);
100
101                                 sb.AppendLine (sfData.ToString ());
102                         }
103
104                         foreach (var m in metadata)
105                                 sb.AppendLine (m.Line);
106                 }
107
108                 private static Dictionary<int, string> ProcessLinesMVID (List<StackTraceMetadata> metadata)
109                 {
110                         var linesMvid = new Dictionary<int, string> ();
111                         var mvidData = metadata.Where ( m => m.Id == "MVID" ).Select ( m => m.Value );
112                         foreach (var m in mvidData) {
113                                 var s1 = m.Split (new char[] {' '}, 2);
114                                 var mvid = s1 [0];
115                                 var lines = s1 [1].Split (',');
116                                 foreach (var line in lines)
117                                         linesMvid.Add (int.Parse (line), mvid);
118                         }
119
120                         return linesMvid;
121                 }
122         }
123 }