5 using System.Collections.Generic;
6 using System.Globalization;
11 public class Symbolicate
14 public readonly int MinArgCount;
15 public readonly int MaxArgCount;
16 public readonly Action<List<string>> Action;
18 public Command (Action<List<string>> action, int minArgCount = 0, int maxArgCount = int.MaxValue)
21 MinArgCount = minArgCount;
22 MaxArgCount = maxArgCount;
26 public static int Main (String[] args)
29 List<string> extra = null;
33 if (args[0] == "store-symbols")
34 cmd = new Command (StoreSymbolsAction, 2);
37 args = args.Skip (1).ToArray ();
39 cmd = new Command (SymbolicateAction, 2, 2);
42 var options = new OptionSet {
43 { "h|help", "Show this help", v => showHelp = true },
47 extra = options.Parse (args);
48 } catch (OptionException e) {
49 Console.WriteLine ("Option error: {0}", e.Message);
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>]+");
57 Console.WriteLine ("Available options:");
58 options.WriteOptionDescriptions (Console.Out);
67 private static void SymbolicateAction (List<string> args)
69 var msymDir = args [0];
70 var inputFile = args [1];
72 var symbolManager = new SymbolManager (msymDir);
74 using (StreamReader r = new StreamReader (inputFile)) {
75 var sb = Process (r, symbolManager);
76 Console.Write (sb.ToString ());
80 private static void StoreSymbolsAction (List<string> args)
82 var msymDir = args[0];
83 var lookupDirs = args.Skip (1).ToArray ();
85 var symbolManager = new SymbolManager (msymDir);
87 symbolManager.StoreSymbols (lookupDirs);
90 public static StringBuilder Process (StreamReader reader, SymbolManager symbolManager)
92 List<StackFrameData> stackFrames = new List<StackFrameData>();
93 List<StackTraceMetadata> metadata = new List<StackTraceMetadata>();
94 StringBuilder sb = new StringBuilder ();
95 bool linesEnded = false;
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);
104 if (stackFrames.Count > 0) {
107 StackTraceMetadata stMetadata;
108 if (StackTraceMetadata.TryParse (line, out stMetadata)) {
109 metadata.Add (stMetadata);
113 DumpStackTrace (symbolManager, sb, stackFrames, metadata);
115 // Clear lists for next stack trace
116 stackFrames.Clear ();
123 sb.AppendLine (line);
126 if (stackFrames.Count > 0)
127 DumpStackTrace (symbolManager, sb, stackFrames, metadata);
132 private static void DumpStackTrace (SymbolManager symbolManager, StringBuilder sb, List<StackFrameData> stackFrames, List<StackTraceMetadata> metadata)
135 var aotidMetadata = metadata.FirstOrDefault ( m => m.Id == "AOTID" );
136 if (aotidMetadata != null)
137 aotid = aotidMetadata.Value;
139 var linesMvid = ProcessLinesMVID (metadata);
141 foreach (var sfData in stackFrames) {
143 if (linesMvid.ContainsKey (lineNumber))
144 mvid = linesMvid [lineNumber++];
146 symbolManager.TryResolveLocation (sfData, mvid, aotid);
148 sb.AppendLine (sfData.ToString ());
151 foreach (var m in metadata)
152 sb.AppendLine (m.Line);
155 private static Dictionary<int, string> ProcessLinesMVID (List<StackTraceMetadata> metadata)
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);
162 var lines = s1 [1].Split (',');
163 foreach (var line in lines)
164 linesMvid.Add (int.Parse (line), mvid);