Cecil update
[mono-project.git] / mcs / tools / mono-symbolicate / SymbolManager.cs
bloba204788306bb274ca648c24aca209d39d34fac60
1 using System;
2 using System.IO;
3 using System.Linq;
4 using System.Text;
5 using System.Collections.Generic;
6 using Mono.Cecil;
7 using Mono.Cecil.Cil;
8 using Mono.Collections.Generic;
10 namespace Mono
12 public class SymbolManager
14 string msymDir;
15 Logger logger;
17 public SymbolManager (string msymDir, Logger logger) {
18 this.msymDir = msymDir;
19 this.logger = logger;
22 internal bool TryResolveLocation (StackFrameData sfData)
24 if (sfData.Mvid == null)
25 return false;
27 var assemblyLocProvider = GetOrCreateAssemblyLocationProvider (sfData.Mvid);
28 if (assemblyLocProvider == null)
29 return false;
31 SeqPointInfo seqPointInfo = null;
32 if (!sfData.IsILOffset && sfData.Aotid != null)
33 seqPointInfo = GetOrCreateSeqPointInfo (sfData.Aotid);
35 return assemblyLocProvider.TryResolveLocation (sfData, seqPointInfo);
38 Dictionary<string, AssemblyLocationProvider> assemblies = new Dictionary<string, AssemblyLocationProvider> ();
40 private AssemblyLocationProvider GetOrCreateAssemblyLocationProvider (string mvid)
42 if (assemblies.ContainsKey (mvid))
43 return assemblies[mvid];
45 var mvidDir = Path.Combine (msymDir, mvid);
46 if (!Directory.Exists (mvidDir)) {
47 logger.LogWarning ("MVID directory does not exist: {0}", mvidDir);
48 return null;
51 string assemblyPath = null;
52 var exeFiles = Directory.GetFiles (mvidDir, "*.exe");
53 var dllFiles = Directory.GetFiles (mvidDir, "*.dll");
55 if (exeFiles.Length + dllFiles.Length != 1) {
56 logger.LogError ("MVID directory should include one assembly: {0}", mvidDir);
57 return null;
60 assemblyPath = exeFiles.Length > 0 ? exeFiles[0] : dllFiles[0];
62 var locProvider = new AssemblyLocationProvider (assemblyPath, logger);
64 assemblies.Add (mvid, locProvider);
66 return locProvider;
69 Dictionary<string, SeqPointInfo> seqPointInfos = new Dictionary<string, SeqPointInfo> ();
71 private SeqPointInfo GetOrCreateSeqPointInfo (string aotid)
73 if (seqPointInfos.ContainsKey (aotid))
74 return seqPointInfos[aotid];
76 var aotidDir = Path.Combine (msymDir, aotid);
77 if (!Directory.Exists (aotidDir)) {
78 logger.LogError ("AOTID directory does not exist: {0}", aotidDir);
79 return null;
82 string msymFile = null;
83 var msymFiles = Directory.GetFiles(aotidDir, "*.msym");
84 msymFile = msymFiles[0];
86 var seqPointInfo = SeqPointInfo.Read (msymFile);
88 seqPointInfos.Add (aotid, seqPointInfo);
90 return seqPointInfo;
93 public void StoreSymbols (params string[] lookupDirs)
95 foreach (var dir in lookupDirs) {
96 var exeFiles = Directory.GetFiles (dir, "*.exe");
97 var dllFiles = Directory.GetFiles (dir, "*.dll");
98 var assemblies = exeFiles.Concat (dllFiles);
99 foreach (var assemblyPath in assemblies) {
101 // TODO: Ignore embedded pdb
102 var symbolFile = GetSymbolFile (assemblyPath);
104 if (symbolFile == null) {
105 logger.LogWarning ("Directory {0} contains {1} but no debug symbols file was found.", dir, Path.GetFileName (assemblyPath));
106 // assemblies without debug symbols are useless
107 continue;
110 var assembly = AssemblyDefinition.ReadAssembly (assemblyPath);
112 var mvid = assembly.MainModule.Mvid.ToString ("N");
113 var mvidDir = Path.Combine (msymDir, mvid);
115 if (Directory.Exists (mvidDir)) {
116 try {
117 Directory.Delete (mvidDir, true);
118 } catch (DirectoryNotFoundException) {}
121 Directory.CreateDirectory (mvidDir);
123 var mvidAssemblyPath = Path.Combine (mvidDir, Path.GetFileName (assemblyPath));
124 File.Copy (assemblyPath, mvidAssemblyPath);
126 var mvidDebugPath = Path.Combine (mvidDir, Path.GetFileName (symbolFile));
127 File.Copy (symbolFile, mvidDebugPath);
129 // TODO create MVID dir for non main modules with links to main module MVID
134 static string GetSymbolFile (string assembly)
136 var pdbName = Path.ChangeExtension (assembly, "pdb");
137 if (File.Exists (pdbName))
138 return pdbName;
140 var mdbName = assembly + ".mdb";
142 if (File.Exists (mdbName))
143 return mdbName;
145 return null;