update Mono.Cecil
[mono.git] / mcs / class / Mono.Cecil / Mono.Cecil.Cil / Symbols.cs
1 //
2 // Symbols.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // Copyright (c) 2008 - 2011 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.IO;
31 using System.Runtime.InteropServices;
32 using SR = System.Reflection;
33
34 using Mono.Collections.Generic;
35
36 namespace Mono.Cecil.Cil {
37
38         [StructLayout (LayoutKind.Sequential)]
39         public struct ImageDebugDirectory {
40                 public int Characteristics;
41                 public int TimeDateStamp;
42                 public short MajorVersion;
43                 public short MinorVersion;
44                 public int Type;
45                 public int SizeOfData;
46                 public int AddressOfRawData;
47                 public int PointerToRawData;
48         }
49
50         public sealed class Scope : IVariableDefinitionProvider {
51
52                 Instruction start;
53                 Instruction end;
54
55                 Collection<Scope> scopes;
56                 Collection<VariableDefinition> variables;
57
58                 public Instruction Start {
59                         get { return start; }
60                         set { start = value; }
61                 }
62
63                 public Instruction End {
64                         get { return end; }
65                         set { end = value; }
66                 }
67
68                 public bool HasScopes {
69                         get { return !scopes.IsNullOrEmpty (); }
70                 }
71
72                 public Collection<Scope> Scopes {
73                         get {
74                                 if (scopes == null)
75                                         scopes = new Collection<Scope> ();
76
77                                 return scopes;
78                         }
79                 }
80
81                 public bool HasVariables {
82                         get { return !variables.IsNullOrEmpty (); }
83                 }
84
85                 public Collection<VariableDefinition> Variables {
86                         get {
87                                 if (variables == null)
88                                         variables = new Collection<VariableDefinition> ();
89
90                                 return variables;
91                         }
92                 }
93         }
94
95         public struct InstructionSymbol {
96
97                 public readonly int Offset;
98                 public readonly SequencePoint SequencePoint;
99
100                 public InstructionSymbol (int offset, SequencePoint sequencePoint)
101                 {
102                         this.Offset = offset;
103                         this.SequencePoint = sequencePoint;
104                 }
105         }
106
107         public sealed class MethodSymbols {
108
109                 internal int code_size;
110                 internal string method_name;
111                 internal MetadataToken method_token;
112                 internal MetadataToken local_var_token;
113                 internal Collection<VariableDefinition> variables;
114                 internal Collection<InstructionSymbol> instructions;
115
116                 public bool HasVariables {
117                         get { return !variables.IsNullOrEmpty (); }
118                 }
119
120                 public Collection<VariableDefinition> Variables {
121                         get {
122                                 if (variables == null)
123                                         variables = new Collection<VariableDefinition> ();
124
125                                 return variables;
126                         }
127                 }
128
129                 public Collection<InstructionSymbol> Instructions {
130                         get {
131                                 if (instructions == null)
132                                         instructions = new Collection<InstructionSymbol> ();
133
134                                 return instructions;
135                         }
136                 }
137
138                 public int CodeSize {
139                         get { return code_size; }
140                 }
141
142                 public string MethodName {
143                         get { return method_name; }
144                 }
145
146                 public MetadataToken MethodToken {
147                         get { return method_token; }
148                 }
149
150                 public MetadataToken LocalVarToken {
151                         get { return local_var_token; }
152                 }
153
154                 internal MethodSymbols (string methodName)
155                 {
156                         this.method_name = methodName;
157                 }
158
159                 public MethodSymbols (MetadataToken methodToken)
160                 {
161                         this.method_token = methodToken;
162                 }
163         }
164
165         public delegate Instruction InstructionMapper (int offset);
166
167         public interface ISymbolReader : IDisposable {
168
169                 bool ProcessDebugHeader (ImageDebugDirectory directory, byte [] header);
170                 void Read (MethodBody body, InstructionMapper mapper);
171                 void Read (MethodSymbols symbols);
172         }
173
174         public interface ISymbolReaderProvider {
175
176                 ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName);
177                 ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream);
178         }
179
180         static class SymbolProvider {
181
182                 static readonly string symbol_kind = Type.GetType ("Mono.Runtime") != null ? "Mdb" : "Pdb";
183
184                 static SR.AssemblyName GetPlatformSymbolAssemblyName ()
185                 {
186                         var cecil_name = typeof (SymbolProvider).Assembly.GetName ();
187
188                         var name = new SR.AssemblyName {
189                                 Name = "Mono.Cecil." + symbol_kind,
190                                 Version = cecil_name.Version,
191                         };
192
193                         name.SetPublicKeyToken (cecil_name.GetPublicKeyToken ());
194
195                         return name;
196                 }
197
198                 static Type GetPlatformType (string fullname)
199                 {
200                         var type = Type.GetType (fullname);
201                         if (type != null)
202                                 return type;
203
204                         var assembly_name = GetPlatformSymbolAssemblyName ();
205
206                         type = Type.GetType (fullname + ", " + assembly_name.FullName);
207                         if (type != null)
208                                 return type;
209
210                         try {
211                                 var assembly = SR.Assembly.Load (assembly_name);
212                                 if (assembly != null)
213                                         return assembly.GetType (fullname);
214                         } catch (FileNotFoundException) {
215 #if !CF
216                         } catch (FileLoadException) {
217 #endif
218                         }
219
220                         return null;
221                 }
222
223                 static ISymbolReaderProvider reader_provider;
224
225                 public static ISymbolReaderProvider GetPlatformReaderProvider ()
226                 {
227                         if (reader_provider != null)
228                                 return reader_provider;
229
230                         var type = GetPlatformType (GetProviderTypeName ("ReaderProvider"));
231                         if (type == null)
232                                 return null;
233
234                         return reader_provider = (ISymbolReaderProvider) Activator.CreateInstance (type);
235                 }
236
237                 static string GetProviderTypeName (string name)
238                 {
239                         return "Mono.Cecil." + symbol_kind + "." + symbol_kind + name;
240                 }
241
242 #if !READ_ONLY
243
244                 static ISymbolWriterProvider writer_provider;
245
246                 public static ISymbolWriterProvider GetPlatformWriterProvider ()
247                 {
248                         if (writer_provider != null)
249                                 return writer_provider;
250
251                         var type = GetPlatformType (GetProviderTypeName ("WriterProvider"));
252                         if (type == null)
253                                 return null;
254
255                         return writer_provider = (ISymbolWriterProvider) Activator.CreateInstance (type);
256                 }
257
258 #endif
259         }
260
261 #if !READ_ONLY
262
263         public interface ISymbolWriter : IDisposable {
264
265                 bool GetDebugHeader (out ImageDebugDirectory directory, out byte [] header);
266                 void Write (MethodBody body);
267                 void Write (MethodSymbols symbols);
268         }
269
270         public interface ISymbolWriterProvider {
271
272                 ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName);
273                 ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream);
274         }
275
276 #endif
277 }