[tests] Remove double inclusion of source file
[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 using Mono.Options;
8
9 namespace Mono
10 {
11         public class Symbolicate
12         {
13                 class Command {
14                         public readonly int MinArgCount;
15                         public readonly int MaxArgCount;
16                         public readonly Action<List<string>> Action;
17
18                         public Command (Action<List<string>> action, int minArgCount = 0, int maxArgCount = int.MaxValue)
19                         {
20                                 Action = action;
21                                 MinArgCount = minArgCount;
22                                 MaxArgCount = maxArgCount;
23                         }
24                 }
25
26                 public static int Main (String[] args)
27                 {
28                         var showHelp = false;
29                         List<string> extra = null;
30
31                         Command cmd = null;
32
33                         if (args[0] == "store-symbols")
34                                 cmd = new Command (StoreSymbolsAction, 2);
35
36                         if (cmd != null) {
37                                 args = args.Skip (1).ToArray ();
38                         } else {
39                                 cmd = new Command (SymbolicateAction, 2, 2);
40                         }
41
42                         var options = new OptionSet {
43                                 { "h|help", "Show this help", v => showHelp = true },
44                         };
45
46                         try {
47                                 extra = options.Parse (args);
48                         } catch (OptionException e) {
49                                 Console.WriteLine ("Option error: {0}", e.Message);
50                                 showHelp = true;
51                         }
52
53                         if (showHelp || extra == null || extra.Count < cmd.MinArgCount || extra.Count > cmd.MaxArgCount) {
54                                 Console.Error.WriteLine ("Usage: symbolicate <msym dir> <input file>");
55                                 Console.Error.WriteLine ("       symbolicate store-symbols <msym dir> [<dir>]+");
56                                 Console.WriteLine ();
57                                 Console.WriteLine ("Available options:");
58                                 options.WriteOptionDescriptions (Console.Out);
59                                 return 1;
60                         }
61
62                         cmd.Action (extra);
63
64                         return 0;
65                 }
66
67                 private static void SymbolicateAction (List<string> args)
68                 {
69                         var msymDir = args [0];
70                         var inputFile = args [1];
71
72                         var symbolManager = new SymbolManager (msymDir);
73
74                         using (StreamReader r = new StreamReader (inputFile)) {
75                                 var sb = Process (r, symbolManager);
76                                 Console.Write (sb.ToString ());
77                         }
78                 }
79
80                 private static void StoreSymbolsAction (List<string> args)
81                 {
82                         var msymDir = args[0];
83                         var lookupDirs = args.Skip (1).ToArray ();
84
85                         var symbolManager = new SymbolManager (msymDir);
86
87                         symbolManager.StoreSymbols (lookupDirs);
88                 }
89
90                 public static StringBuilder Process (StreamReader reader, SymbolManager symbolManager)
91                 {
92                         List<StackFrameData> stackFrames = new List<StackFrameData>();
93                         List<StackTraceMetadata> metadata = new List<StackTraceMetadata>();
94                         StringBuilder sb = new StringBuilder ();
95                         bool linesEnded = false;
96
97                         for (var line = reader.ReadLine (); line != null; line = reader.ReadLine ()) {
98                                 StackFrameData sfData;
99                                 if (!linesEnded && StackFrameData.TryParse (line, out sfData)) {
100                                         stackFrames.Add (sfData);
101                                         continue;
102                                 }
103
104                                 if (stackFrames.Count > 0) {
105                                         linesEnded = true;
106
107                                         StackTraceMetadata stMetadata;
108                                         if (StackTraceMetadata.TryParse (line, out stMetadata)) {
109                                                 metadata.Add (stMetadata);
110                                                 continue;
111                                         }
112
113                                         DumpStackTrace (symbolManager, sb, stackFrames, metadata);
114                 
115                                         // Clear lists for next stack trace
116                                         stackFrames.Clear ();
117                                         metadata.Clear ();
118                                 }
119
120                                 linesEnded = false;
121
122                                 // Append last line
123                                 sb.AppendLine (line);
124                         }
125
126                         if (stackFrames.Count > 0)
127                                 DumpStackTrace (symbolManager, sb, stackFrames, metadata);
128
129                         return sb;
130                 }
131
132                 private static void DumpStackTrace (SymbolManager symbolManager, StringBuilder sb, List<StackFrameData> stackFrames, List<StackTraceMetadata> metadata)
133                 {
134                         string aotid = null;
135                         var aotidMetadata = metadata.FirstOrDefault ( m => m.Id == "AOTID" );
136                         if (aotidMetadata != null)
137                                 aotid = aotidMetadata.Value;
138
139                         var linesMvid = ProcessLinesMVID (metadata);
140                         var lineNumber = 0;
141                         foreach (var sfData in stackFrames) {
142                                 string mvid = null;
143                                 if (linesMvid.ContainsKey (lineNumber))
144                                         mvid = linesMvid [lineNumber++];
145
146                                 symbolManager.TryResolveLocation (sfData, mvid, aotid);
147
148                                 sb.AppendLine (sfData.ToString ());
149                         }
150
151                         foreach (var m in metadata)
152                                 sb.AppendLine (m.Line);
153                 }
154
155                 private static Dictionary<int, string> ProcessLinesMVID (List<StackTraceMetadata> metadata)
156                 {
157                         var linesMvid = new Dictionary<int, string> ();
158                         var mvidData = metadata.Where ( m => m.Id == "MVID" ).Select ( m => m.Value );
159                         foreach (var m in mvidData) {
160                                 var s1 = m.Split (new char[] {' '}, 2);
161                                 var mvid = s1 [0];
162                                 var lines = s1 [1].Split (',');
163                                 foreach (var line in lines)
164                                         linesMvid.Add (int.Parse (line), mvid);
165                         }
166
167                         return linesMvid;
168                 }
169         }
170 }