[msvc] Update csproj files (#4074)
[mono.git] / mcs / tools / mono-symbolicate / symbolicate.cs
index 93cbabc0a9bdd57c46e5bd30f7e9d2b66814fe78..2c04a27eef04e84b37cd51a2b4b9b78a83be4358 100644 (file)
 using System;
 using System.IO;
+using System.Text;
+using System.Linq;
+using System.Collections.Generic;
 using System.Globalization;
-using System.Text.RegularExpressions;
+using Mono.Options;
 
-namespace Symbolicate
+namespace Mono
 {
-       public class Program
+       public class Symbolicate
        {
-               static Regex regex = new Regex (@"\w*at (?<MethodName>.+) \((?<MethodParams>.*)\) *(\[0x(?<IL>.+)\]|<0x.* \+ 0x(?<NativeOffset>.+)>) in <filename unknown>:0");
+               class Command {
+                       public readonly int MinArgCount;
+                       public readonly int MaxArgCount;
+                       public readonly Action<List<string>> Action;
+
+                       public Command (Action<List<string>> action, int minArgCount = 0, int maxArgCount = int.MaxValue)
+                       {
+                               Action = action;
+                               MinArgCount = minArgCount;
+                               MaxArgCount = maxArgCount;
+                       }
+               }
+
+               static Logger logger;
 
                public static int Main (String[] args)
                {
-                       if (args.Length < 2) {
-                               Console.Error.WriteLine ("Usage: symbolicate <assembly path> <input file> [lookup directories]");
-                               return 1;
-                       }
+                       var showHelp = false;
+                       List<string> extra = null;
 
-                       var assemblyPath = args [0];
-                       var inputFile = args [1];
+                       Command cmd = null;
 
-                       var locProvider = new LocationProvider ();
+                       var logLevel = Logger.Level.Warning;
 
-                       for (var i = 2; i < args.Length; i++)
-                               locProvider.AddDirectory (args [i]);
+                       var options = new OptionSet {
+                               { "h|help", "Show this help", v => showHelp = true },
+                               { "q", "Quiet, warnings are not displayed", v => logLevel = Logger.Level.Error },
+                               { "v", "Verbose, log debug messages", v => logLevel = Logger.Level.Debug },
+                       };
 
-                       locProvider.AddAssembly (assemblyPath);
+                       try {
+                               extra = options.Parse (args);
+                       } catch (OptionException e) {
+                               Console.WriteLine ("Option error: {0}", e.Message);
+                               showHelp = true;
+                       }
 
-                       using (StreamReader r = new StreamReader (inputFile)) {
-                           for (var line = r.ReadLine (); line != null; line = r.ReadLine ()) {
-                                       line = SymbolicateLine (line, locProvider);
-                                       Console.WriteLine (line);
-                           }
+                       if (extra.Count > 0 && extra[0] == "store-symbols")
+                               cmd = new Command (StoreSymbolsAction, 2);
+
+                       if (cmd != null) {
+                               extra.RemoveAt (0);
+                       } else {
+                               cmd = new Command (SymbolicateAction, 2, 2);
                        }
 
+                       if (showHelp || extra == null || extra.Count < cmd.MinArgCount || extra.Count > cmd.MaxArgCount) {
+                               Console.Error.WriteLine ("Usage: symbolicate [options] <msym dir> <input file>");
+                               Console.Error.WriteLine ("       symbolicate [options] store-symbols <msym dir> [<dir>]+");
+                               Console.WriteLine ();
+                               Console.WriteLine ("Available options:");
+                               options.WriteOptionDescriptions (Console.Out);
+                               return 1;
+                       }
+
+                       logger = new Logger (logLevel, msg => Console.Error.WriteLine (msg));
+
+                       cmd.Action (extra);
+
                        return 0;
                }
 
-               static string SymbolicateLine (string line, LocationProvider locProvider)
+               private static void SymbolicateAction (List<string> args)
                {
-                       var match = regex.Match (line);
-                       if (!match.Success)
-                               return line;
-
-                       var methodName = match.Groups ["MethodName"].Value;
-                       var methodParams = ParseParametersTypes (match.Groups ["MethodParams"].Value);
+                       var msymDir = args [0];
+                       var inputFile = args [1];
 
-                       var isOffsetIL = !string.IsNullOrEmpty (match.Groups ["IL"].Value);
-                       var offsetVarName = (isOffsetIL)? "IL" : "NativeOffset";
-                       var offset = int.Parse (match.Groups [offsetVarName].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
+                       var symbolManager = new SymbolManager (msymDir, logger);
 
-                       Location location;
-                       if (!locProvider.TryGetLocation (methodName, methodParams, offset, isOffsetIL, out location))
-                               return line;
+                       using (StreamReader r = new StreamReader (inputFile)) {
+                               for (var line = r.ReadLine (); line != null; line = r.ReadLine ()) {
+                                       StackFrameData sfData;
+                                       if (StackFrameData.TryParse (line, out sfData) &&
+                                               symbolManager.TryResolveLocation (sfData)) {
+                                               Console.WriteLine (sfData.ToString ());
+                                               continue;
+                                       }
 
-                       return line.Replace ("<filename unknown>:0", string.Format ("{0}:{1}", location.FileName, location.Line));
+                                       Console.WriteLine (line);
+                               }
+                       }
                }
 
-               static string[] ParseParametersTypes (string parameters)
+               private static void StoreSymbolsAction (List<string> args)
                {
-                       if (string.IsNullOrEmpty (parameters))
-                               return new string [0];
+                       var msymDir = args[0];
+                       var lookupDirs = args.Skip (1).ToArray ();
 
-                       var paramsArray = parameters.Split (',');
-                       var paramsTypes = new string [paramsArray.Length];
-                       for (var i = 0; i < paramsArray.Length; i++)
-                               paramsTypes [i] = paramsArray [i].Trim ().Split (new char[]{' '}, 2)[0];
+                       var symbolManager = new SymbolManager (msymDir, logger);
 
-                       return paramsTypes;
+                       symbolManager.StoreSymbols (lookupDirs);
                }
        }
-}
\ No newline at end of file
+}