Xamarin Public Jenkins (auto-signing) 7d7f676260 Imported Upstream version 5.16.0.100
Former-commit-id: 38faa55fb9669e35e7d8448b15c25dc447f25767
2018-08-07 15:19:03 +00:00

168 lines
4.4 KiB
C#

using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
namespace Mono
{
// Should be (string File, int Line) but need to bump monodroid_tools to 4.7
readonly struct Location
{
public readonly string File;
public readonly int Line;
public Location (string file, int line)
{
File = file;
Line = line;
}
}
public class SymbolManager
{
string msymDir;
Logger logger;
public SymbolManager (string msymDir, Logger logger) {
this.msymDir = msymDir;
this.logger = logger;
}
internal bool TryResolveLocation (StackFrameData sfData, out Location location)
{
if (sfData.Mvid == null) {
location = default;
return false;
}
var assemblyLocProvider = GetOrCreateAssemblyLocationProvider (sfData.Mvid);
if (assemblyLocProvider == null) {
location = default;
return false;
}
SeqPointInfo seqPointInfo = null;
if (!sfData.IsILOffset && sfData.Aotid != null)
seqPointInfo = GetOrCreateSeqPointInfo (sfData.Aotid);
return assemblyLocProvider.TryResolveLocation (sfData, seqPointInfo, out location);
}
Dictionary<string, AssemblyLocationProvider> assemblies = new Dictionary<string, AssemblyLocationProvider> ();
private AssemblyLocationProvider GetOrCreateAssemblyLocationProvider (string mvid)
{
if (assemblies.ContainsKey (mvid))
return assemblies[mvid];
var mvidDir = Path.Combine (msymDir, mvid);
if (!Directory.Exists (mvidDir)) {
logger.LogWarning ("MVID directory does not exist: {0}", mvidDir);
return null;
}
string assemblyPath = null;
var exeFiles = Directory.GetFiles (mvidDir, "*.exe");
var dllFiles = Directory.GetFiles (mvidDir, "*.dll");
if (exeFiles.Length + dllFiles.Length != 1) {
logger.LogError ("MVID directory should include one assembly: {0}", mvidDir);
return null;
}
assemblyPath = exeFiles.Length > 0 ? exeFiles[0] : dllFiles[0];
var locProvider = new AssemblyLocationProvider (assemblyPath, logger);
assemblies.Add (mvid, locProvider);
return locProvider;
}
Dictionary<string, SeqPointInfo> seqPointInfos = new Dictionary<string, SeqPointInfo> ();
private SeqPointInfo GetOrCreateSeqPointInfo (string aotid)
{
if (seqPointInfos.ContainsKey (aotid))
return seqPointInfos[aotid];
var aotidDir = Path.Combine (msymDir, aotid);
if (!Directory.Exists (aotidDir)) {
logger.LogError ("AOTID directory does not exist: {0}", aotidDir);
return null;
}
string msymFile = null;
var msymFiles = Directory.GetFiles(aotidDir, "*.msym");
msymFile = msymFiles[0];
var seqPointInfo = SeqPointInfo.Read (msymFile);
seqPointInfos.Add (aotid, seqPointInfo);
return seqPointInfo;
}
public void StoreSymbols (params string[] lookupDirs)
{
foreach (var dir in lookupDirs) {
var exeFiles = Directory.GetFiles (dir, "*.exe");
var dllFiles = Directory.GetFiles (dir, "*.dll");
var assemblies = exeFiles.Concat (dllFiles);
foreach (var assemblyPath in assemblies) {
// TODO: Ignore embedded pdb
var symbolFile = GetSymbolFile (assemblyPath);
if (symbolFile == null) {
logger.LogWarning ("Directory {0} contains {1} but no debug symbols file was found.", dir, Path.GetFileName (assemblyPath));
// assemblies without debug symbols are useless
continue;
}
string mvidDir;
using (var assembly = AssemblyDefinition.ReadAssembly (assemblyPath)) {
var mvid = assembly.MainModule.Mvid.ToString ("N");
mvidDir = Path.Combine (msymDir, mvid);
}
if (Directory.Exists (mvidDir)) {
try {
Directory.Delete (mvidDir, true);
} catch (DirectoryNotFoundException) {}
}
Directory.CreateDirectory (mvidDir);
var mvidAssemblyPath = Path.Combine (mvidDir, Path.GetFileName (assemblyPath));
File.Copy (assemblyPath, mvidAssemblyPath);
var mvidDebugPath = Path.Combine (mvidDir, Path.GetFileName (symbolFile));
File.Copy (symbolFile, mvidDebugPath);
// TODO create MVID dir for non main modules with links to main module MVID
}
}
}
static string GetSymbolFile (string assembly)
{
var pdbName = Path.ChangeExtension (assembly, "pdb");
if (File.Exists (pdbName))
return pdbName;
var mdbName = assembly + ".mdb";
if (File.Exists (mdbName))
return mdbName;
return null;
}
}
}