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

@ -2,167 +2,170 @@ using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.CompilerServices.SymbolWriter;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
namespace Symbolicate
namespace Mono
{
struct Location {
public string FileName;
public int Line;
}
class AssemblyLocationProvider
{
AssemblyDefinition assembly;
Logger logger;
class LocationProvider {
class AssemblyLocationProvider {
Assembly assembly;
MonoSymbolFile symbolFile;
string seqPointDataPath;
public AssemblyLocationProvider (Assembly assembly, MonoSymbolFile symbolFile, string seqPointDataPath)
{
this.assembly = assembly;
this.symbolFile = symbolFile;
this.seqPointDataPath = seqPointDataPath;
}
public bool TryGetLocation (string methodStr, string typeFullName, int offset, bool isOffsetIL, uint methodIndex, out Location location)
{
location = default (Location);
if (symbolFile == null)
return false;
var type = assembly.GetTypes().FirstOrDefault (t => t.FullName == typeFullName);
if (type == null)
return false;
var bindingflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
var method = type.GetMethods(bindingflags).FirstOrDefault (m => GetMethodFullName (m) == methodStr);
if (method == null)
return false;
int ilOffset = (isOffsetIL)? offset : GetILOffsetFromFile (method.MetadataToken, methodIndex, offset);
if (ilOffset < 0)
return false;
var methodSymbol = symbolFile.Methods [(method.MetadataToken & 0x00ffffff) - 1];
var lineNumbers = methodSymbol.GetLineNumberTable ().LineNumbers;
var lineNumber = lineNumbers.FirstOrDefault (l => l.Offset >= ilOffset) ?? lineNumbers.Last ();
location.FileName = symbolFile.Sources [lineNumber.File-1].FileName;
location.Line = lineNumber.Row;
return true;
}
static MethodInfo methodGetIL;
private int GetILOffsetFromFile (int methodToken, uint methodIndex, int nativeOffset)
{
if (string.IsNullOrEmpty (seqPointDataPath))
return -1;
if (methodGetIL == null)
methodGetIL = typeof (StackFrame).GetMethod ("GetILOffsetFromFile", BindingFlags.NonPublic | BindingFlags.Static);
if (methodGetIL == null)
throw new Exception ("System.Diagnostics.StackFrame.GetILOffsetFromFile could not be found, make sure you have an updated mono installed.");
return (int) methodGetIL.Invoke (null, new object[] {seqPointDataPath, methodToken, methodIndex, nativeOffset});
}
static MethodInfo methodGetMethodFullName;
private string GetMethodFullName (MethodBase m)
{
if (methodGetMethodFullName == null)
methodGetMethodFullName = typeof (StackTrace).GetMethod ("GetFullNameForStackTrace", BindingFlags.NonPublic | BindingFlags.Static);
if (methodGetMethodFullName == null)
throw new Exception ("System.Exception.GetFullNameForStackTrace could not be found, make sure you have an updated mono installed.");
StringBuilder sb = new StringBuilder ();
methodGetMethodFullName.Invoke (null, new object[] {sb, m});
return sb.ToString ();
}
}
Dictionary<string, AssemblyLocationProvider> assemblies;
HashSet<string> directories;
public LocationProvider () {
assemblies = new Dictionary<string, AssemblyLocationProvider> ();
directories = new HashSet<string> ();
}
public void AddAssembly (string assemblyPath)
public AssemblyLocationProvider (string assemblyPath, Logger logger)
{
assemblyPath = Path.GetFullPath (assemblyPath);
if (assemblies.ContainsKey (assemblyPath))
return;
this.logger = logger;
if (!File.Exists (assemblyPath))
throw new ArgumentException ("assemblyPath does not exist: "+ assemblyPath);
var assembly = Assembly.LoadFrom (assemblyPath);
MonoSymbolFile symbolFile = null;
var readerParameters = new ReaderParameters { ReadSymbols = true };
assembly = AssemblyDefinition.ReadAssembly (assemblyPath, readerParameters);
}
var symbolPath = assemblyPath + ".mdb";
if (!File.Exists (symbolPath))
Debug.WriteLine (".mdb file was not found for " + assemblyPath);
else
symbolFile = MonoSymbolFile.ReadSymbolFile (assemblyPath + ".mdb");
public bool TryResolveLocation (StackFrameData sfData, SeqPointInfo seqPointInfo)
{
if (!assembly.MainModule.HasSymbols)
return false;
var seqPointDataPath = assemblyPath + ".msym";
if (!File.Exists (seqPointDataPath))
seqPointDataPath = null;
assemblies.Add (assemblyPath, new AssemblyLocationProvider (assembly, symbolFile, seqPointDataPath));
directories.Add (Path.GetDirectoryName (assemblyPath));
foreach (var assemblyRef in assembly.GetReferencedAssemblies ()) {
string refPath = null;
foreach (var dir in directories) {
refPath = Path.Combine (dir, assemblyRef.Name);
if (File.Exists (refPath))
break;
refPath = Path.Combine (dir, assemblyRef.Name + ".dll");
if (File.Exists (refPath))
break;
refPath = Path.Combine (dir, assemblyRef.Name + ".exe");
if (File.Exists (refPath))
break;
refPath = null;
TypeDefinition type = null;
var nested = sfData.TypeFullName.Split ('+');
var types = assembly.MainModule.Types;
foreach (var ntype in nested) {
if (type == null) {
// Use namespace first time.
type = types.FirstOrDefault (t => t.FullName == ntype);
} else {
type = types.FirstOrDefault (t => t.Name == ntype);
}
if (refPath != null)
AddAssembly (refPath);
}
}
public void AddDirectory (string directory)
{
directory = Path.GetFullPath (directory);
if (!Directory.Exists (directory)) {
Console.Error.WriteLine ("Directory " + directory + " does not exist.");
return;
if (type == null) {
logger.LogWarning ("Could not find type: {0}", ntype);
return false;
}
types = type.NestedTypes;
}
directories.Add (directory);
}
var parensStart = sfData.MethodSignature.IndexOf ('(');
var methodName = sfData.MethodSignature.Substring (0, parensStart).TrimEnd ();
var methodParameters = sfData.MethodSignature.Substring (parensStart);
var method = type.Methods.FirstOrDefault (m => CompareName (m, methodName) && CompareParameters (m.Parameters, methodParameters));
if (method == null) {
logger.LogWarning ("Could not find method: {0}", methodName);
return false;
}
public bool TryGetLocation (string method, string typeFullName, int offset, bool isOffsetIL, uint methodIndex, out Location location)
{
location = default (Location);
foreach (var assembly in assemblies.Values) {
if (assembly.TryGetLocation (method, typeFullName, offset, isOffsetIL, methodIndex, out location))
int ilOffset;
if (sfData.IsILOffset) {
ilOffset = sfData.Offset;
} else {
if (seqPointInfo == null)
return false;
ilOffset = seqPointInfo.GetILOffset (method.MetadataToken.ToInt32 (), sfData.MethodIndex, sfData.Offset);
}
if (ilOffset < 0)
return false;
SequencePoint sp = null;
foreach (var instr in method.Body.Instructions) {
if (instr.SequencePoint != null)
sp = instr.SequencePoint;
if (instr.Offset >= ilOffset) {
sfData.SetLocation (sp.Document.Url, sp.StartLine);
return true;
}
}
return false;
}
static bool CompareName (MethodDefinition candidate, string expected)
{
if (candidate.Name == expected)
return true;
if (!candidate.HasGenericParameters)
return false;
var genStart = expected.IndexOf ('[');
if (genStart < 0)
return false;
if (candidate.Name != expected.Substring (0, genStart))
return false;
int arity = 1;
for (int pos = genStart; pos < expected.Length; ++pos) {
if (expected [pos] == ',')
++arity;
}
return candidate.GenericParameters.Count == arity;
}
static bool CompareParameters (Collection<ParameterDefinition> candidate, string expected)
{
var builder = new StringBuilder ();
builder.Append ("(");
for (int i = 0; i < candidate.Count; i++) {
var parameter = candidate [i];
if (i > 0)
builder.Append (", ");
if (parameter.ParameterType.IsSentinel)
builder.Append ("...,");
var pt = parameter.ParameterType;
if (!string.IsNullOrEmpty (pt.Namespace)) {
builder.Append (pt.Namespace);
builder.Append (".");
}
FormatElementType (pt, builder);
builder.Append (" ");
builder.Append (parameter.Name);
}
builder.Append (")");
return builder.ToString () == expected;
}
static void FormatElementType (TypeReference tr, StringBuilder builder)
{
var ts = tr as TypeSpecification;
if (ts != null) {
if (ts.IsByReference) {
FormatElementType (ts.ElementType, builder);
builder.Append ("&");
return;
}
var array = ts as ArrayType;
if (array != null) {
FormatElementType (ts.ElementType, builder);
builder.Append ("[");
for (int ii = 0; ii < array.Rank - 1; ++ii) {
builder.Append (",");
}
builder.Append ("]");
return;
}
}
builder.Append (tr.Name);
}
}
}