MdbWriter.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. //
  2. // Author:
  3. // Jb Evain (jbevain@gmail.com)
  4. //
  5. // Copyright (c) 2008 - 2015 Jb Evain
  6. // Copyright (c) 2008 - 2011 Novell, Inc.
  7. //
  8. // Licensed under the MIT/X11 license.
  9. //
  10. using System;
  11. using System.Collections.Generic;
  12. using System.IO;
  13. using ILRuntime.Mono.Cecil.Cil;
  14. using ILRuntime.Mono.Collections.Generic;
  15. using ILRuntime.Mono.CompilerServices.SymbolWriter;
  16. namespace ILRuntime.Mono.Cecil.Mdb {
  17. public sealed class MdbWriterProvider : ISymbolWriterProvider {
  18. public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName)
  19. {
  20. Mixin.CheckModule (module);
  21. Mixin.CheckFileName (fileName);
  22. return new MdbWriter (module, fileName);
  23. }
  24. public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream)
  25. {
  26. throw new NotImplementedException ();
  27. }
  28. }
  29. public sealed class MdbWriter : ISymbolWriter {
  30. readonly ModuleDefinition module;
  31. readonly MonoSymbolWriter writer;
  32. readonly Dictionary<string, SourceFile> source_files;
  33. public MdbWriter (ModuleDefinition module, string assembly)
  34. {
  35. this.module = module;
  36. this.writer = new MonoSymbolWriter (assembly);
  37. this.source_files = new Dictionary<string, SourceFile> ();
  38. }
  39. public ISymbolReaderProvider GetReaderProvider ()
  40. {
  41. return new MdbReaderProvider ();
  42. }
  43. SourceFile GetSourceFile (Document document)
  44. {
  45. var url = document.Url;
  46. SourceFile source_file;
  47. if (source_files.TryGetValue (url, out source_file))
  48. return source_file;
  49. var entry = writer.DefineDocument (url, null, document.Hash != null && document.Hash.Length == 16 ? document.Hash : null);
  50. var compile_unit = writer.DefineCompilationUnit (entry);
  51. source_file = new SourceFile (compile_unit, entry);
  52. source_files.Add (url, source_file);
  53. return source_file;
  54. }
  55. void Populate (Collection<SequencePoint> sequencePoints, int [] offsets,
  56. int [] startRows, int [] endRows, int [] startCols, int [] endCols, out SourceFile file)
  57. {
  58. SourceFile source_file = null;
  59. for (int i = 0; i < sequencePoints.Count; i++) {
  60. var sequence_point = sequencePoints [i];
  61. offsets [i] = sequence_point.Offset;
  62. if (source_file == null)
  63. source_file = GetSourceFile (sequence_point.Document);
  64. startRows [i] = sequence_point.StartLine;
  65. endRows [i] = sequence_point.EndLine;
  66. startCols [i] = sequence_point.StartColumn;
  67. endCols [i] = sequence_point.EndColumn;
  68. }
  69. file = source_file;
  70. }
  71. public void Write (MethodDebugInformation info)
  72. {
  73. var method = new SourceMethod (info.method);
  74. var sequence_points = info.SequencePoints;
  75. int count = sequence_points.Count;
  76. if (count == 0)
  77. return;
  78. var offsets = new int [count];
  79. var start_rows = new int [count];
  80. var end_rows = new int [count];
  81. var start_cols = new int [count];
  82. var end_cols = new int [count];
  83. SourceFile file;
  84. Populate (sequence_points, offsets, start_rows, end_rows, start_cols, end_cols, out file);
  85. var builder = writer.OpenMethod (file.CompilationUnit, 0, method);
  86. for (int i = 0; i < count; i++) {
  87. builder.MarkSequencePoint (
  88. offsets [i],
  89. file.CompilationUnit.SourceFile,
  90. start_rows [i],
  91. start_cols [i],
  92. end_rows [i],
  93. end_cols [i],
  94. false);
  95. }
  96. if (info.scope != null)
  97. WriteRootScope (info.scope, info);
  98. writer.CloseMethod ();
  99. }
  100. void WriteRootScope (ScopeDebugInformation scope, MethodDebugInformation info)
  101. {
  102. WriteScopeVariables (scope);
  103. if (scope.HasScopes)
  104. WriteScopes (scope.Scopes, info);
  105. }
  106. void WriteScope (ScopeDebugInformation scope, MethodDebugInformation info)
  107. {
  108. writer.OpenScope (scope.Start.Offset);
  109. WriteScopeVariables (scope);
  110. if (scope.HasScopes)
  111. WriteScopes (scope.Scopes, info);
  112. writer.CloseScope (scope.End.IsEndOfMethod ? info.code_size : scope.End.Offset);
  113. }
  114. void WriteScopes (Collection<ScopeDebugInformation> scopes, MethodDebugInformation info)
  115. {
  116. for (int i = 0; i < scopes.Count; i++)
  117. WriteScope (scopes [i], info);
  118. }
  119. void WriteScopeVariables (ScopeDebugInformation scope)
  120. {
  121. if (!scope.HasVariables)
  122. return;
  123. foreach (var variable in scope.variables)
  124. if (!string.IsNullOrEmpty (variable.Name))
  125. writer.DefineLocalVariable (variable.Index, variable.Name);
  126. }
  127. public ImageDebugHeader GetDebugHeader ()
  128. {
  129. return new ImageDebugHeader ();
  130. }
  131. public void Dispose ()
  132. {
  133. writer.WriteSymbolFile (module.Mvid);
  134. }
  135. class SourceFile : ISourceFile {
  136. readonly CompileUnitEntry compilation_unit;
  137. readonly SourceFileEntry entry;
  138. public SourceFileEntry Entry {
  139. get { return entry; }
  140. }
  141. public CompileUnitEntry CompilationUnit {
  142. get { return compilation_unit; }
  143. }
  144. public SourceFile (CompileUnitEntry comp_unit, SourceFileEntry entry)
  145. {
  146. this.compilation_unit = comp_unit;
  147. this.entry = entry;
  148. }
  149. }
  150. class SourceMethod : IMethodDef {
  151. readonly MethodDefinition method;
  152. public string Name {
  153. get { return method.Name; }
  154. }
  155. public int Token {
  156. get { return method.MetadataToken.ToInt32 (); }
  157. }
  158. public SourceMethod (MethodDefinition method)
  159. {
  160. this.method = method;
  161. }
  162. }
  163. }
  164. }