1 // 2 // SymbolWriterImpl.cs 3 // 4 // Author: 5 // Lluis Sanchez Gual (lluis@novell.com) 6 // 7 // (C) 2005 Novell, Inc. http://www.novell.com 8 // 9 // 10 // Permission is hereby granted, free of charge, to any person obtaining 11 // a copy of this software and associated documentation files (the 12 // "Software"), to deal in the Software without restriction, including 13 // without limitation the rights to use, copy, modify, merge, publish, 14 // distribute, sublicense, and/or sell copies of the Software, and to 15 // permit persons to whom the Software is furnished to do so, subject to 16 // the following conditions: 17 // 18 // The above copyright notice and this permission notice shall be 19 // included in all copies or substantial portions of the Software. 20 // 21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 // 29 30 31 using System; 32 using System.Reflection; 33 using System.Reflection.Emit; 34 using System.Runtime.CompilerServices; 35 using System.Collections; 36 using System.IO; 37 using System.Diagnostics.SymbolStore; 38 39 namespace Mono.CompilerServices.SymbolWriter 40 { 41 public class SymbolWriterImpl: ISymbolWriter 42 { 43 MonoSymbolWriter msw; 44 45 int nextLocalIndex; 46 int currentToken; 47 string methodName; 48 Stack namespaceStack = new Stack (); 49 bool methodOpened; 50 51 Hashtable documents = new Hashtable (); 52 53 #if !CECIL && !MOBILE 54 ModuleBuilder mb; GetGuidFunc(ModuleBuilder mb)55 delegate Guid GetGuidFunc (ModuleBuilder mb); 56 GetGuidFunc get_guid_func; 57 SymbolWriterImpl(ModuleBuilder mb)58 public SymbolWriterImpl (ModuleBuilder mb) 59 { 60 this.mb = mb; 61 } 62 Close()63 public void Close () 64 { 65 MethodInfo mi = typeof (ModuleBuilder).GetMethod ( 66 "Mono_GetGuid", 67 BindingFlags.Static | BindingFlags.NonPublic); 68 if (mi == null) 69 return; 70 71 get_guid_func = (GetGuidFunc) System.Delegate.CreateDelegate ( 72 typeof (GetGuidFunc), mi); 73 74 msw.WriteSymbolFile (get_guid_func (mb)); 75 } 76 #else 77 Guid guid; 78 SymbolWriterImpl(Guid guid)79 public SymbolWriterImpl (Guid guid) 80 { 81 this.guid = guid; 82 } 83 Close()84 public void Close () 85 { 86 msw.WriteSymbolFile (guid); 87 } 88 #endif 89 CloseMethod()90 public void CloseMethod () 91 { 92 if (methodOpened) { 93 methodOpened = false; 94 nextLocalIndex = 0; 95 msw.CloseMethod (); 96 } 97 } 98 CloseNamespace()99 public void CloseNamespace () 100 { 101 namespaceStack.Pop (); 102 msw.CloseNamespace (); 103 } 104 CloseScope(int endOffset)105 public void CloseScope (int endOffset) 106 { 107 msw.CloseScope (endOffset); 108 } 109 DefineDocument( string url, Guid language, Guid languageVendor, Guid documentType)110 public ISymbolDocumentWriter DefineDocument ( 111 string url, 112 Guid language, 113 Guid languageVendor, 114 Guid documentType) 115 { 116 SymbolDocumentWriterImpl doc = (SymbolDocumentWriterImpl) documents [url]; 117 if (doc == null) { 118 SourceFileEntry entry = msw.DefineDocument (url); 119 CompileUnitEntry comp_unit = msw.DefineCompilationUnit (entry); 120 doc = new SymbolDocumentWriterImpl (comp_unit); 121 documents [url] = doc; 122 } 123 return doc; 124 } 125 DefineField( SymbolToken parent, string name, FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3)126 public void DefineField ( 127 SymbolToken parent, 128 string name, 129 FieldAttributes attributes, 130 byte[] signature, 131 SymAddressKind addrKind, 132 int addr1, 133 int addr2, 134 int addr3) 135 { 136 } 137 DefineGlobalVariable( string name, FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3)138 public void DefineGlobalVariable ( 139 string name, 140 FieldAttributes attributes, 141 byte[] signature, 142 SymAddressKind addrKind, 143 int addr1, 144 int addr2, 145 int addr3) 146 { 147 } 148 DefineLocalVariable( string name, FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset)149 public void DefineLocalVariable ( 150 string name, 151 FieldAttributes attributes, 152 byte[] signature, 153 SymAddressKind addrKind, 154 int addr1, 155 int addr2, 156 int addr3, 157 int startOffset, 158 int endOffset) 159 { 160 msw.DefineLocalVariable (nextLocalIndex++, name); 161 } 162 DefineParameter( string name, ParameterAttributes attributes, int sequence, SymAddressKind addrKind, int addr1, int addr2, int addr3)163 public void DefineParameter ( 164 string name, 165 ParameterAttributes attributes, 166 int sequence, 167 SymAddressKind addrKind, 168 int addr1, 169 int addr2, 170 int addr3) 171 { 172 } 173 DefineSequencePoints( ISymbolDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns)174 public void DefineSequencePoints ( 175 ISymbolDocumentWriter document, 176 int[] offsets, 177 int[] lines, 178 int[] columns, 179 int[] endLines, 180 int[] endColumns) 181 { 182 SymbolDocumentWriterImpl doc = (SymbolDocumentWriterImpl) document; 183 SourceFileEntry file = doc != null ? doc.Entry.SourceFile : null; 184 185 for (int n=0; n<offsets.Length; n++) { 186 if (n > 0 && offsets[n] == offsets[n-1] && lines[n] == lines[n-1] && columns[n] == columns[n-1]) 187 continue; 188 msw.MarkSequencePoint (offsets[n], file, lines[n], columns[n], false); 189 } 190 } 191 Initialize(IntPtr emitter, string filename, bool fFullBuild)192 public void Initialize (IntPtr emitter, string filename, bool fFullBuild) 193 { 194 msw = new MonoSymbolWriter (filename); 195 } 196 OpenMethod(SymbolToken method)197 public void OpenMethod (SymbolToken method) 198 { 199 currentToken = method.GetToken (); 200 } 201 OpenNamespace(string name)202 public void OpenNamespace (string name) 203 { 204 NamespaceInfo n = new NamespaceInfo (); 205 n.NamespaceID = -1; 206 n.Name = name; 207 namespaceStack.Push (n); 208 } 209 OpenScope(int startOffset)210 public int OpenScope (int startOffset) 211 { 212 return msw.OpenScope (startOffset); 213 } 214 SetMethodSourceRange( ISymbolDocumentWriter startDoc, int startLine, int startColumn, ISymbolDocumentWriter endDoc, int endLine, int endColumn)215 public void SetMethodSourceRange ( 216 ISymbolDocumentWriter startDoc, 217 int startLine, 218 int startColumn, 219 ISymbolDocumentWriter endDoc, 220 int endLine, 221 int endColumn) 222 { 223 int nsId = GetCurrentNamespace (startDoc); 224 SourceMethodImpl sm = new SourceMethodImpl (methodName, currentToken, nsId); 225 msw.OpenMethod (((ICompileUnit)startDoc).Entry, nsId, sm); 226 methodOpened = true; 227 } 228 SetScopeRange(int scopeID, int startOffset, int endOffset)229 public void SetScopeRange (int scopeID, int startOffset, int endOffset) 230 { 231 } 232 SetSymAttribute(SymbolToken parent, string name, byte[] data)233 public void SetSymAttribute (SymbolToken parent, string name, byte[] data) 234 { 235 // This is a hack! but MonoSymbolWriter needs the method name 236 // and ISymbolWriter does not have any method for providing it 237 if (name == "__name") 238 methodName = System.Text.Encoding.UTF8.GetString (data); 239 } 240 SetUnderlyingWriter(IntPtr underlyingWriter)241 public void SetUnderlyingWriter (IntPtr underlyingWriter) 242 { 243 } 244 SetUserEntryPoint(SymbolToken entryMethod)245 public void SetUserEntryPoint (SymbolToken entryMethod) 246 { 247 } 248 UsingNamespace(string fullName)249 public void UsingNamespace (string fullName) 250 { 251 if (namespaceStack.Count == 0) { 252 OpenNamespace (""); 253 } 254 255 NamespaceInfo ni = (NamespaceInfo) namespaceStack.Peek (); 256 if (ni.NamespaceID != -1) { 257 NamespaceInfo old = ni; 258 CloseNamespace (); 259 OpenNamespace (old.Name); 260 ni = (NamespaceInfo) namespaceStack.Peek (); 261 ni.UsingClauses = old.UsingClauses; 262 } 263 ni.UsingClauses.Add (fullName); 264 } 265 GetCurrentNamespace(ISymbolDocumentWriter doc)266 int GetCurrentNamespace (ISymbolDocumentWriter doc) 267 { 268 if (namespaceStack.Count == 0) { 269 OpenNamespace (""); 270 } 271 272 NamespaceInfo ni = (NamespaceInfo) namespaceStack.Peek (); 273 if (ni.NamespaceID == -1) 274 { 275 string[] usings = (string[]) ni.UsingClauses.ToArray (typeof(string)); 276 277 int parentId = 0; 278 if (namespaceStack.Count > 1) { 279 namespaceStack.Pop (); 280 parentId = ((NamespaceInfo) namespaceStack.Peek ()).NamespaceID; 281 namespaceStack.Push (ni); 282 } 283 284 ni.NamespaceID = msw.DefineNamespace (ni.Name, ((ICompileUnit)doc).Entry, usings, parentId); 285 } 286 return ni.NamespaceID; 287 } 288 289 } 290 291 class SymbolDocumentWriterImpl: ISymbolDocumentWriter, ISourceFile, ICompileUnit 292 { 293 CompileUnitEntry comp_unit; 294 SymbolDocumentWriterImpl(CompileUnitEntry comp_unit)295 public SymbolDocumentWriterImpl (CompileUnitEntry comp_unit) 296 { 297 this.comp_unit = comp_unit; 298 } 299 SetCheckSum(Guid algorithmId, byte[] checkSum)300 public void SetCheckSum (Guid algorithmId, byte[] checkSum) 301 { 302 } 303 SetSource(byte[] source)304 public void SetSource (byte[] source) 305 { 306 } 307 308 SourceFileEntry ISourceFile.Entry { 309 get { return comp_unit.SourceFile; } 310 } 311 312 public CompileUnitEntry Entry { 313 get { return comp_unit; } 314 } 315 } 316 317 class SourceMethodImpl: IMethodDef 318 { 319 string name; 320 int token; 321 int namespaceID; 322 SourceMethodImpl(string name, int token, int namespaceID)323 public SourceMethodImpl (string name, int token, int namespaceID) 324 { 325 this.name = name; 326 this.token = token; 327 this.namespaceID = namespaceID; 328 } 329 330 public string Name { 331 get { return name; } 332 } 333 334 public int NamespaceID { 335 get { return namespaceID; } 336 } 337 338 public int Token { 339 get { return token; } 340 } 341 } 342 343 class NamespaceInfo 344 { 345 public string Name; 346 public int NamespaceID; 347 public ArrayList UsingClauses = new ArrayList (); 348 } 349 } 350