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 
InstructionSymbolMono.Cecil.Cil.InstructionSymbol100 		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 		public 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 
MethodSymbols(string methodName)154 		internal MethodSymbols (string methodName)
155 		{
156 			this.method_name = methodName;
157 		}
158 
MethodSymbols(MetadataToken methodToken)159 		public MethodSymbols (MetadataToken methodToken)
160 		{
161 			this.method_token = methodToken;
162 		}
163 	}
164 
InstructionMapper(int offset)165 	public delegate Instruction InstructionMapper (int offset);
166 
167 	public interface ISymbolReader : IDisposable {
168 
ProcessDebugHeader(ImageDebugDirectory directory, byte [] header)169 		bool ProcessDebugHeader (ImageDebugDirectory directory, byte [] header);
Read(MethodBody body, InstructionMapper mapper)170 		void Read (MethodBody body, InstructionMapper mapper);
Read(MethodSymbols symbols)171 		void Read (MethodSymbols symbols);
172 	}
173 
174 	public interface ISymbolReaderProvider {
175 
GetSymbolReader(ModuleDefinition module, string fileName)176 		ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName);
GetSymbolReader(ModuleDefinition module, Stream symbolStream)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 
GetPlatformSymbolAssemblyName()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.VB." + symbol_kind,
190 				Version = cecil_name.Version,
191 			};
192 
193 			name.SetPublicKeyToken (cecil_name.GetPublicKeyToken ());
194 
195 			return name;
196 		}
197 
GetPlatformType(string fullname)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 
GetPlatformReaderProvider()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 
GetProviderTypeName(string name)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 
GetPlatformWriterProvider()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 
GetDebugHeader(out ImageDebugDirectory directory, out byte [] header)265 		bool GetDebugHeader (out ImageDebugDirectory directory, out byte [] header);
Write(MethodBody body)266 		void Write (MethodBody body);
Write(MethodSymbols symbols)267 		void Write (MethodSymbols symbols);
268 	}
269 
270 	public interface ISymbolWriterProvider {
271 
GetSymbolWriter(ModuleDefinition module, string fileName)272 		ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName);
GetSymbolWriter(ModuleDefinition module, Stream symbolStream)273 		ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream);
274 	}
275 
276 #endif
277 }
278