Xamarin Public Jenkins (auto-signing) e79aa3c0ed Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
2016-08-03 10:59:49 +00:00

182 lines
4.7 KiB
C#

using System;
using System.IO;
using System.Text;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using Mono.Options;
namespace Mono
{
public class Symbolicate
{
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)
{
var showHelp = false;
List<string> extra = null;
Command cmd = null;
var logLevel = Logger.Level.Warning;
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 },
};
try {
extra = options.Parse (args);
} catch (OptionException e) {
Console.WriteLine ("Option error: {0}", e.Message);
showHelp = true;
}
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;
}
private static void SymbolicateAction (List<string> args)
{
var msymDir = args [0];
var inputFile = args [1];
var symbolManager = new SymbolManager (msymDir, logger);
using (StreamReader r = new StreamReader (inputFile)) {
var sb = Process (r, symbolManager);
Console.Write (sb.ToString ());
}
}
private static void StoreSymbolsAction (List<string> args)
{
var msymDir = args[0];
var lookupDirs = args.Skip (1).ToArray ();
var symbolManager = new SymbolManager (msymDir, logger);
symbolManager.StoreSymbols (lookupDirs);
}
public static StringBuilder Process (StreamReader reader, SymbolManager symbolManager)
{
List<StackFrameData> stackFrames = new List<StackFrameData>();
List<StackTraceMetadata> metadata = new List<StackTraceMetadata>();
StringBuilder sb = new StringBuilder ();
bool linesEnded = false;
for (var line = reader.ReadLine (); line != null; line = reader.ReadLine ()) {
StackFrameData sfData;
if (!linesEnded && StackFrameData.TryParse (line, out sfData)) {
stackFrames.Add (sfData);
continue;
}
if (stackFrames.Count > 0) {
linesEnded = true;
StackTraceMetadata stMetadata;
if (StackTraceMetadata.TryParse (line, out stMetadata)) {
metadata.Add (stMetadata);
continue;
}
DumpStackTrace (symbolManager, sb, stackFrames, metadata);
// Clear lists for next stack trace
stackFrames.Clear ();
metadata.Clear ();
}
linesEnded = false;
// Append last line
sb.AppendLine (line);
}
if (stackFrames.Count > 0)
DumpStackTrace (symbolManager, sb, stackFrames, metadata);
return sb;
}
private static void DumpStackTrace (SymbolManager symbolManager, StringBuilder sb, List<StackFrameData> stackFrames, List<StackTraceMetadata> metadata)
{
string aotid = null;
var aotidMetadata = metadata.FirstOrDefault ( m => m.Id == "AOTID" );
if (aotidMetadata != null)
aotid = aotidMetadata.Value;
var linesMvid = ProcessLinesMVID (metadata);
var lineNumber = -1;
foreach (var sfData in stackFrames) {
string mvid = null;
lineNumber++;
if (!sfData.IsValid)
continue;
if (linesMvid.ContainsKey (lineNumber))
mvid = linesMvid [lineNumber];
symbolManager.TryResolveLocation (sfData, mvid, aotid);
sb.AppendLine (sfData.ToString ());
}
foreach (var m in metadata)
sb.AppendLine (m.Line);
}
private static Dictionary<int, string> ProcessLinesMVID (List<StackTraceMetadata> metadata)
{
var linesMvid = new Dictionary<int, string> ();
var mvidData = metadata.Where ( m => m.Id == "MVID" ).Select ( m => m.Value );
foreach (var m in mvidData) {
var s1 = m.Split (new char[] {' '}, 2);
var mvid = s1 [0];
var lines = s1 [1].Split (',');
foreach (var line in lines)
linesMvid.Add (int.Parse (line), mvid);
}
return linesMvid;
}
}
}