Imported Upstream version 4.6.0.125

Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-08-03 10:59:49 +00:00
parent a569aebcfd
commit e79aa3c0ed
17047 changed files with 3137615 additions and 392334 deletions

View File

@@ -1,89 +1,181 @@
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 (?<Method>.+) *(\[0x(?<IL>.+)\]|<0x.+ \+ 0x(?<NativeOffset>.+)>( (?<MethodIndex>\d+)|)) 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]");
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;
}
var assemblyPath = args [0];
var inputFile = args [1];
logger = new Logger (logLevel, msg => Console.Error.WriteLine (msg));
var locProvider = new LocationProvider ();
for (var i = 2; i < args.Length; i++)
locProvider.AddDirectory (args [i]);
locProvider.AddAssembly (assemblyPath);
using (StreamReader r = new StreamReader (inputFile)) {
for (var line = r.ReadLine (); line != null; line = r.ReadLine ()) {
line = SymbolicateLine (line, locProvider);
Console.WriteLine (line);
}
}
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 msymDir = args [0];
var inputFile = args [1];
string typeFullName;
var methodStr = match.Groups ["Method"].Value.Trim ();
if (!TryParseMethodType (methodStr, out typeFullName))
return line;
var symbolManager = new SymbolManager (msymDir, logger);
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);
uint methodIndex = 0xffffff;
if (!string.IsNullOrEmpty (match.Groups ["MethodIndex"].Value))
methodIndex = uint.Parse (match.Groups ["MethodIndex"].Value, CultureInfo.InvariantCulture);
Location location;
if (!locProvider.TryGetLocation (methodStr, typeFullName, offset, isOffsetIL, methodIndex, out location))
return line;
return line.Replace ("<filename unknown>:0", string.Format ("{0}:{1}", location.FileName, location.Line));
using (StreamReader r = new StreamReader (inputFile)) {
var sb = Process (r, symbolManager);
Console.Write (sb.ToString ());
}
}
static bool TryParseMethodType (string str, out string typeFullName)
private static void StoreSymbolsAction (List<string> args)
{
typeFullName = null;
var msymDir = args[0];
var lookupDirs = args.Skip (1).ToArray ();
var methodNameEnd = str.IndexOf ("(");
if (methodNameEnd == -1)
return false;
var symbolManager = new SymbolManager (msymDir, logger);
// Remove parameters
str = str.Substring (0, methodNameEnd);
symbolManager.StoreSymbols (lookupDirs);
}
// Remove generic parameters
str = Regex.Replace (str, @"\[[^\[\]]*\]", "");
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;
var typeNameEnd = str.LastIndexOf (".");
if (methodNameEnd == -1 || typeNameEnd == -1)
return false;
for (var line = reader.ReadLine (); line != null; line = reader.ReadLine ()) {
StackFrameData sfData;
if (!linesEnded && StackFrameData.TryParse (line, out sfData)) {
stackFrames.Add (sfData);
continue;
}
// Remove method name
typeFullName = str.Substring (0, typeNameEnd);
if (stackFrames.Count > 0) {
linesEnded = true;
return 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;
}
}
}
}