/symbols/mdb/Mono.CompilerServices.SymbolWriter/SymbolWriterImpl.cs

http://github.com/jbevain/cecil · C# · 352 lines · 271 code · 51 blank · 30 comment · 25 complexity · 2a3acd3bf499b97f4e4d800512102430 MD5 · raw file

  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. #if !NET_CORE
  30. using System;
  31. using System.Reflection;
  32. using System.Reflection.Emit;
  33. using System.Runtime.CompilerServices;
  34. using System.Collections;
  35. using System.IO;
  36. using System.Diagnostics.SymbolStore;
  37. namespace Mono.CompilerServices.SymbolWriter
  38. {
  39. public class SymbolWriterImpl: ISymbolWriter
  40. {
  41. MonoSymbolWriter msw;
  42. int nextLocalIndex;
  43. int currentToken;
  44. string methodName;
  45. Stack namespaceStack = new Stack ();
  46. bool methodOpened;
  47. Hashtable documents = new Hashtable ();
  48. #if !CECIL
  49. ModuleBuilder mb;
  50. delegate Guid GetGuidFunc (ModuleBuilder mb);
  51. GetGuidFunc get_guid_func;
  52. public SymbolWriterImpl (ModuleBuilder mb)
  53. {
  54. this.mb = mb;
  55. }
  56. public void Close ()
  57. {
  58. MethodInfo mi = typeof (ModuleBuilder).GetMethod (
  59. "Mono_GetGuid",
  60. BindingFlags.Static | BindingFlags.NonPublic);
  61. if (mi == null)
  62. return;
  63. get_guid_func = (GetGuidFunc) System.Delegate.CreateDelegate (
  64. typeof (GetGuidFunc), mi);
  65. msw.WriteSymbolFile (get_guid_func (mb));
  66. }
  67. #else
  68. Guid guid;
  69. public SymbolWriterImpl (Guid guid)
  70. {
  71. this.guid = guid;
  72. }
  73. public void Close ()
  74. {
  75. msw.WriteSymbolFile (guid);
  76. }
  77. #endif
  78. public void CloseMethod ()
  79. {
  80. if (methodOpened) {
  81. methodOpened = false;
  82. nextLocalIndex = 0;
  83. msw.CloseMethod ();
  84. }
  85. }
  86. public void CloseNamespace ()
  87. {
  88. namespaceStack.Pop ();
  89. msw.CloseNamespace ();
  90. }
  91. public void CloseScope (int endOffset)
  92. {
  93. msw.CloseScope (endOffset);
  94. }
  95. public ISymbolDocumentWriter DefineDocument (
  96. string url,
  97. Guid language,
  98. Guid languageVendor,
  99. Guid documentType)
  100. {
  101. SymbolDocumentWriterImpl doc = (SymbolDocumentWriterImpl) documents [url];
  102. if (doc == null) {
  103. SourceFileEntry entry = msw.DefineDocument (url);
  104. CompileUnitEntry comp_unit = msw.DefineCompilationUnit (entry);
  105. doc = new SymbolDocumentWriterImpl (comp_unit);
  106. documents [url] = doc;
  107. }
  108. return doc;
  109. }
  110. public void DefineField (
  111. SymbolToken parent,
  112. string name,
  113. FieldAttributes attributes,
  114. byte[] signature,
  115. SymAddressKind addrKind,
  116. int addr1,
  117. int addr2,
  118. int addr3)
  119. {
  120. }
  121. public void DefineGlobalVariable (
  122. string name,
  123. FieldAttributes attributes,
  124. byte[] signature,
  125. SymAddressKind addrKind,
  126. int addr1,
  127. int addr2,
  128. int addr3)
  129. {
  130. }
  131. public void DefineLocalVariable (
  132. string name,
  133. FieldAttributes attributes,
  134. byte[] signature,
  135. SymAddressKind addrKind,
  136. int addr1,
  137. int addr2,
  138. int addr3,
  139. int startOffset,
  140. int endOffset)
  141. {
  142. msw.DefineLocalVariable (nextLocalIndex++, name);
  143. }
  144. public void DefineParameter (
  145. string name,
  146. ParameterAttributes attributes,
  147. int sequence,
  148. SymAddressKind addrKind,
  149. int addr1,
  150. int addr2,
  151. int addr3)
  152. {
  153. }
  154. public void DefineSequencePoints (
  155. ISymbolDocumentWriter document,
  156. int[] offsets,
  157. int[] lines,
  158. int[] columns,
  159. int[] endLines,
  160. int[] endColumns)
  161. {
  162. SymbolDocumentWriterImpl doc = (SymbolDocumentWriterImpl) document;
  163. SourceFileEntry file = doc != null ? doc.Entry.SourceFile : null;
  164. for (int n=0; n<offsets.Length; n++) {
  165. if (n > 0 && offsets[n] == offsets[n-1] && lines[n] == lines[n-1] && columns[n] == columns[n-1])
  166. continue;
  167. msw.MarkSequencePoint (offsets[n], file, lines[n], columns[n], false);
  168. }
  169. }
  170. public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
  171. {
  172. msw = new MonoSymbolWriter (filename);
  173. }
  174. public void OpenMethod (SymbolToken method)
  175. {
  176. currentToken = method.GetToken ();
  177. }
  178. public void OpenNamespace (string name)
  179. {
  180. NamespaceInfo n = new NamespaceInfo ();
  181. n.NamespaceID = -1;
  182. n.Name = name;
  183. namespaceStack.Push (n);
  184. }
  185. public int OpenScope (int startOffset)
  186. {
  187. return msw.OpenScope (startOffset);
  188. }
  189. public void SetMethodSourceRange (
  190. ISymbolDocumentWriter startDoc,
  191. int startLine,
  192. int startColumn,
  193. ISymbolDocumentWriter endDoc,
  194. int endLine,
  195. int endColumn)
  196. {
  197. int nsId = GetCurrentNamespace (startDoc);
  198. SourceMethodImpl sm = new SourceMethodImpl (methodName, currentToken, nsId);
  199. msw.OpenMethod (((ICompileUnit)startDoc).Entry, nsId, sm);
  200. methodOpened = true;
  201. }
  202. public void SetScopeRange (int scopeID, int startOffset, int endOffset)
  203. {
  204. }
  205. public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
  206. {
  207. // This is a hack! but MonoSymbolWriter needs the method name
  208. // and ISymbolWriter does not have any method for providing it
  209. if (name == "__name")
  210. methodName = System.Text.Encoding.UTF8.GetString (data);
  211. }
  212. public void SetUnderlyingWriter (IntPtr underlyingWriter)
  213. {
  214. }
  215. public void SetUserEntryPoint (SymbolToken entryMethod)
  216. {
  217. }
  218. public void UsingNamespace (string fullName)
  219. {
  220. if (namespaceStack.Count == 0) {
  221. OpenNamespace ("");
  222. }
  223. NamespaceInfo ni = (NamespaceInfo) namespaceStack.Peek ();
  224. if (ni.NamespaceID != -1) {
  225. NamespaceInfo old = ni;
  226. CloseNamespace ();
  227. OpenNamespace (old.Name);
  228. ni = (NamespaceInfo) namespaceStack.Peek ();
  229. ni.UsingClauses = old.UsingClauses;
  230. }
  231. ni.UsingClauses.Add (fullName);
  232. }
  233. int GetCurrentNamespace (ISymbolDocumentWriter doc)
  234. {
  235. if (namespaceStack.Count == 0) {
  236. OpenNamespace ("");
  237. }
  238. NamespaceInfo ni = (NamespaceInfo) namespaceStack.Peek ();
  239. if (ni.NamespaceID == -1)
  240. {
  241. string[] usings = (string[]) ni.UsingClauses.ToArray (typeof(string));
  242. int parentId = 0;
  243. if (namespaceStack.Count > 1) {
  244. namespaceStack.Pop ();
  245. parentId = ((NamespaceInfo) namespaceStack.Peek ()).NamespaceID;
  246. namespaceStack.Push (ni);
  247. }
  248. ni.NamespaceID = msw.DefineNamespace (ni.Name, ((ICompileUnit)doc).Entry, usings, parentId);
  249. }
  250. return ni.NamespaceID;
  251. }
  252. }
  253. class SymbolDocumentWriterImpl: ISymbolDocumentWriter, ISourceFile, ICompileUnit
  254. {
  255. CompileUnitEntry comp_unit;
  256. public SymbolDocumentWriterImpl (CompileUnitEntry comp_unit)
  257. {
  258. this.comp_unit = comp_unit;
  259. }
  260. public void SetCheckSum (Guid algorithmId, byte[] checkSum)
  261. {
  262. }
  263. public void SetSource (byte[] source)
  264. {
  265. }
  266. SourceFileEntry ISourceFile.Entry {
  267. get { return comp_unit.SourceFile; }
  268. }
  269. public CompileUnitEntry Entry {
  270. get { return comp_unit; }
  271. }
  272. }
  273. class SourceMethodImpl: IMethodDef
  274. {
  275. string name;
  276. int token;
  277. int namespaceID;
  278. public SourceMethodImpl (string name, int token, int namespaceID)
  279. {
  280. this.name = name;
  281. this.token = token;
  282. this.namespaceID = namespaceID;
  283. }
  284. public string Name {
  285. get { return name; }
  286. }
  287. public int NamespaceID {
  288. get { return namespaceID; }
  289. }
  290. public int Token {
  291. get { return token; }
  292. }
  293. }
  294. class NamespaceInfo
  295. {
  296. public string Name;
  297. public int NamespaceID;
  298. public ArrayList UsingClauses = new ArrayList ();
  299. }
  300. }
  301. #endif