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