Added Mono.Tasklets test
[mono.git] / mcs / tools / mono-symbolicate / SymbolManager.cs
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;
9
10 namespace Mono
11 {
12         public class SymbolManager
13         {
14                 string msymDir;
15
16                 public SymbolManager (string msymDir) {
17                         this.msymDir = msymDir;
18                 }
19
20                 internal bool TryResolveLocation (StackFrameData sfData, string mvid, string aotid)
21                 {
22                         var assemblyLocProvider = GetOrCreateAssemblyLocationProvider (mvid);
23
24                         SeqPointInfo seqPointInfo = null;
25                         if (!sfData.IsILOffset && aotid != null)
26                                 seqPointInfo = GetOrCreateSeqPointInfo (aotid);
27
28                         return assemblyLocProvider.TryResolveLocation (sfData, seqPointInfo);
29                 }
30
31                 Dictionary<string, AssemblyLocationProvider> assemblies = new Dictionary<string, AssemblyLocationProvider> ();
32
33                 private AssemblyLocationProvider GetOrCreateAssemblyLocationProvider (string mvid)
34                 {
35                         if (assemblies.ContainsKey (mvid))
36                                 return assemblies[mvid];
37
38                         var mvidDir = Path.Combine (msymDir, mvid);
39                         if (!Directory.Exists (mvidDir))
40                                 throw new Exception (string.Format("MVID directory does not exist: {0}", mvidDir));
41
42                         string assemblyPath = null;
43                         var exeFiles = Directory.GetFiles (mvidDir, "*.exe");
44                         var dllFiles = Directory.GetFiles (mvidDir, "*.dll");
45
46                         if (exeFiles.Length + dllFiles.Length != 1)
47                                 throw new Exception (string.Format ("MVID directory should include one assembly: {0}", mvidDir));
48
49                         assemblyPath = (exeFiles.Length > 0)? exeFiles[0] : dllFiles[0];
50
51                         var locProvider = new AssemblyLocationProvider (assemblyPath);
52
53                         assemblies.Add (mvid, locProvider);
54
55                         return locProvider;
56                 }
57
58                 Dictionary<string, SeqPointInfo> seqPointInfos = new Dictionary<string, SeqPointInfo> ();
59
60                 private SeqPointInfo GetOrCreateSeqPointInfo (string aotid)
61                 {
62                         if (seqPointInfos.ContainsKey (aotid))
63                                 return seqPointInfos[aotid];
64
65                         var aotidDir = Path.Combine (msymDir, aotid);
66                         if (!Directory.Exists (aotidDir))
67                                 throw new Exception (string.Format("AOTID directory does not exist: {0}", aotidDir));
68
69                         string msymFile = null;
70                         var msymFiles = Directory.GetFiles(aotidDir, "*.msym");
71                         msymFile = msymFiles[0];
72
73                         var seqPointInfo = SeqPointInfo.Read (msymFile);
74
75                         seqPointInfos.Add (aotid, seqPointInfo);
76
77                         return seqPointInfo;
78                 }
79
80                 public void StoreSymbols (params string[] lookupDirs)
81                 {
82                         foreach (var dir in lookupDirs) {
83                                 var exeFiles = Directory.GetFiles (dir, "*.exe");
84                                 var dllFiles = Directory.GetFiles (dir, "*.dll");
85                                 var assemblies = exeFiles.Concat (dllFiles);
86                                 foreach (var assemblyPath in assemblies) {
87                                         var mdbPath = assemblyPath + ".mdb";
88                                         if (!File.Exists (mdbPath)) {
89                                                 // assemblies without mdb files are useless
90                                                 continue;
91                                         }
92
93                                         var assembly = AssemblyDefinition.ReadAssembly (assemblyPath);
94
95                                         var mvid = assembly.MainModule.Mvid.ToString ("N");
96                                         var mvidDir = Path.Combine (msymDir, mvid);
97
98                                         Directory.CreateDirectory (mvidDir);
99
100                                         var mvidAssemblyPath = Path.Combine (mvidDir, Path.GetFileName (assemblyPath));
101                                         File.Copy (assemblyPath, mvidAssemblyPath);
102
103                                         var mvidMdbPath = Path.Combine (mvidDir, Path.GetFileName (mdbPath));
104                                         File.Copy (mdbPath, mvidMdbPath);
105
106                                         // TODO create MVID dir for non main modules with links to main module MVID
107                                 }
108                         }
109                 }
110         }
111 }