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;
28 public static int Main (String[] args)
31 List<string> extra = null;
35 if (args[0] == "store-symbols")
36 cmd = new Command (StoreSymbolsAction, 2);
39 args = args.Skip (1).ToArray ();
41 cmd = new Command (SymbolicateAction, 2, 2);
44 var logLevel = Logger.Level.Warning;
46 var options = new OptionSet {
47 { "h|help", "Show this help", v => showHelp = true },
48 { "q", "Quiet, warnings are not displayed", v => logLevel = Logger.Level.Error },
49 { "v", "Verbose, log debug messages", v => logLevel = Logger.Level.Debug },
53 extra = options.Parse (args);
54 } catch (OptionException e) {
55 Console.WriteLine ("Option error: {0}", e.Message);
59 if (showHelp || extra == null || extra.Count < cmd.MinArgCount || extra.Count > cmd.MaxArgCount) {
60 Console.Error.WriteLine ("Usage: symbolicate <msym dir> <input file>");
61 Console.Error.WriteLine (" symbolicate store-symbols <msym dir> [<dir>]+");
63 Console.WriteLine ("Available options:");
64 options.WriteOptionDescriptions (Console.Out);
68 logger = new Logger (logLevel, msg => Console.Error.WriteLine (msg));
75 private static void SymbolicateAction (List<string> args)
77 var msymDir = args [0];
78 var inputFile = args [1];
80 var symbolManager = new SymbolManager (msymDir, logger);
82 using (StreamReader r = new StreamReader (inputFile)) {
83 var sb = Process (r, symbolManager);
84 Console.Write (sb.ToString ());
88 private static void StoreSymbolsAction (List<string> args)
90 var msymDir = args[0];
91 var lookupDirs = args.Skip (1).ToArray ();
93 var symbolManager = new SymbolManager (msymDir, logger);
95 symbolManager.StoreSymbols (lookupDirs);
98 public static StringBuilder Process (StreamReader reader, SymbolManager symbolManager)
100 List<StackFrameData> stackFrames = new List<StackFrameData>();
101 List<StackTraceMetadata> metadata = new List<StackTraceMetadata>();
102 StringBuilder sb = new StringBuilder ();
103 bool linesEnded = false;
105 for (var line = reader.ReadLine (); line != null; line = reader.ReadLine ()) {
106 StackFrameData sfData;
107 if (!linesEnded && StackFrameData.TryParse (line, out sfData)) {
108 stackFrames.Add (sfData);
112 if (stackFrames.Count > 0) {
115 StackTraceMetadata stMetadata;
116 if (StackTraceMetadata.TryParse (line, out stMetadata)) {
117 metadata.Add (stMetadata);
121 DumpStackTrace (symbolManager, sb, stackFrames, metadata);
123 // Clear lists for next stack trace
124 stackFrames.Clear ();
131 sb.AppendLine (line);
134 if (stackFrames.Count > 0)
135 DumpStackTrace (symbolManager, sb, stackFrames, metadata);
140 private static void DumpStackTrace (SymbolManager symbolManager, StringBuilder sb, List<StackFrameData> stackFrames, List<StackTraceMetadata> metadata)
143 var aotidMetadata = metadata.FirstOrDefault ( m => m.Id == "AOTID" );
144 if (aotidMetadata != null)
145 aotid = aotidMetadata.Value;
147 var linesMvid = ProcessLinesMVID (metadata);
149 foreach (var sfData in stackFrames) {
151 if (linesMvid.ContainsKey (lineNumber))
152 mvid = linesMvid [lineNumber++];
154 symbolManager.TryResolveLocation (sfData, mvid, aotid);
156 sb.AppendLine (sfData.ToString ());
159 foreach (var m in metadata)
160 sb.AppendLine (m.Line);
163 private static Dictionary<int, string> ProcessLinesMVID (List<StackTraceMetadata> metadata)
165 var linesMvid = new Dictionary<int, string> ();
166 var mvidData = metadata.Where ( m => m.Id == "MVID" ).Select ( m => m.Value );
167 foreach (var m in mvidData) {
168 var s1 = m.Split (new char[] {' '}, 2);
170 var lines = s1 [1].Split (',');
171 foreach (var line in lines)
172 linesMvid.Add (int.Parse (line), mvid);