2 // System.Diagnostics.SymbolStore/MonoSymbolWriter.cs
5 // Martin Baulig (martin@gnome.org)
7 // This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter
10 // (C) 2002 Ximian, Inc. http://www.ximian.com
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Runtime.CompilerServices;
17 using System.Diagnostics.SymbolStore;
18 using System.Collections;
21 namespace Mono.CSharp.Debugger
23 internal class SourceFile
25 private ArrayList _methods = new ArrayList ();
26 private string _file_name;
28 public SourceFile (string filename)
30 this._file_name = filename;
33 public override string ToString ()
38 public string FileName {
44 public SourceMethod[] Methods {
46 SourceMethod[] retval = new SourceMethod [_methods.Count];
47 _methods.CopyTo (retval);
52 public void AddMethod (SourceMethod method)
54 _methods.Add (method);
58 internal class SourceBlock
60 static private int next_index;
61 private readonly int _index;
63 public SourceBlock (SourceMethod method, SourceLine start, SourceLine end)
65 this._method = method;
68 this._index = ++next_index;
71 internal SourceBlock (SourceMethod method, int startOffset)
73 this._method = method;
74 this._start = new SourceLine (startOffset);
75 this._index = ++next_index;
78 public override string ToString ()
80 return "SourceBlock #" + ID + " (" + Start + " - " + End + ")";
83 private readonly SourceMethod _method;
84 private ArrayList _blocks = new ArrayList ();
85 internal SourceLine _start;
86 internal SourceLine _end;
88 private ArrayList _locals = new ArrayList ();
90 public SourceMethod SourceMethod {
96 public SourceBlock[] Blocks {
98 SourceBlock[] retval = new SourceBlock [_blocks.Count];
99 _blocks.CopyTo (retval);
104 public void AddBlock (SourceBlock block)
109 public SourceLine Start {
115 public SourceLine End {
127 public LocalVariableEntry[] Locals {
129 LocalVariableEntry[] retval = new LocalVariableEntry [_locals.Count];
130 _locals.CopyTo (retval);
135 public void AddLocal (LocalVariableEntry local)
141 internal class SourceLine
143 public SourceLine (int row, int column)
144 : this (0, row, column)
146 this._type = SourceOffsetType.OFFSET_NONE;
149 public SourceLine (int offset, int row, int column)
151 this._offset = offset;
153 this._column = column;
154 this._type = SourceOffsetType.OFFSET_IL;
157 internal SourceLine (int offset)
158 : this (offset, 0, 0)
161 public override string ToString ()
163 return "SourceLine (" + _offset + "@" + _row + ":" + _column + ")";
166 internal SourceOffsetType _type;
167 internal int _offset;
169 internal int _column;
171 // interface SourceLine
173 public SourceOffsetType OffsetType {
198 internal class SourceMethod
200 private ArrayList _lines = new ArrayList ();
201 private ArrayList _blocks = new ArrayList ();
202 private Hashtable _block_hash = new Hashtable ();
203 private Stack _block_stack = new Stack ();
205 internal readonly MethodBase _method_base;
206 internal SourceFile _source_file;
209 private SourceBlock _implicit_block;
211 public SourceMethod (MethodBase method_base, SourceFile source_file)
214 this._source_file = source_file;
217 internal SourceMethod (MethodBase method_base)
219 this._method_base = method_base;
221 this._implicit_block = new SourceBlock (this, 0);
224 public void SetSourceRange (SourceFile sourceFile,
225 int startLine, int startColumn,
226 int endLine, int endColumn)
228 _source_file = sourceFile;
229 _implicit_block._start = new SourceLine (startLine, startColumn);
230 _implicit_block._end = new SourceLine (endLine, endColumn);
234 public void StartBlock (SourceBlock block)
236 _block_stack.Push (block);
239 public void EndBlock (int endOffset) {
240 SourceBlock block = (SourceBlock) _block_stack.Pop ();
242 block._end = new SourceLine (endOffset);
244 if (_block_stack.Count > 0) {
245 SourceBlock parent = (SourceBlock) _block_stack.Peek ();
247 parent.AddBlock (block);
251 _block_hash.Add (block.ID, block);
254 public void SetBlockRange (int BlockID, int startOffset, int endOffset)
256 SourceBlock block = (SourceBlock) _block_hash [BlockID];
257 ((SourceLine) block.Start)._offset = startOffset;
258 ((SourceLine) block.End)._offset = endOffset;
261 public SourceBlock CurrentBlock {
263 if (_block_stack.Count > 0)
264 return (SourceBlock) _block_stack.Peek ();
266 return _implicit_block;
270 public SourceLine[] Lines {
272 SourceLine[] retval = new SourceLine [_lines.Count];
273 _lines.CopyTo (retval);
278 public void AddLine (SourceLine line)
283 public SourceBlock[] Blocks {
285 SourceBlock[] retval = new SourceBlock [_blocks.Count];
286 _blocks.CopyTo (retval);
291 public LocalVariableEntry[] Locals {
293 return _implicit_block.Locals;
297 public void AddLocal (LocalVariableEntry local)
299 _implicit_block.AddLocal (local);
302 public MethodBase MethodBase {
308 public string FullName {
310 return _method_base.DeclaringType.FullName + "." + _method_base.Name;
314 public Type ReturnType {
316 if (_method_base is MethodInfo)
317 return ((MethodInfo)_method_base).ReturnType;
318 else if (_method_base is ConstructorInfo)
319 return _method_base.DeclaringType;
321 throw new NotSupportedException ();
325 public ParameterInfo[] Parameters {
327 if (_method_base == null)
328 return new ParameterInfo [0];
330 ParameterInfo [] retval = _method_base.GetParameters ();
332 return new ParameterInfo [0];
338 public SourceFile SourceFile {
349 throw new NotSupportedException ();
353 public SourceLine Start {
355 if (_implicit_block.Start == null)
357 else if (_implicit_block.Start.Row == 0)
360 return _implicit_block.Start;
364 public SourceLine End {
366 return _implicit_block.End;
371 public class MonoSymbolWriter : IMonoSymbolWriter
373 protected Assembly assembly;
374 protected ModuleBuilder module_builder;
375 protected ArrayList locals = null;
376 protected ArrayList orphant_methods = null;
377 protected ArrayList methods = null;
378 protected Hashtable sources = null;
379 private ArrayList mbuilder_array = null;
381 internal SourceMethod[] Methods {
383 SourceMethod[] retval = new SourceMethod [methods.Count];
384 methods.CopyTo (retval);
389 internal SourceFile[] Sources {
391 SourceFile[] retval = new SourceFile [sources.Count];
392 sources.Values.CopyTo (retval, 0);
397 private SourceMethod current_method = null;
398 private string assembly_filename = null;
399 private string output_filename = null;
402 // Interface IMonoSymbolWriter
405 public MonoSymbolWriter (ModuleBuilder mb, string filename, ArrayList mbuilder_array)
407 this.assembly_filename = filename;
408 this.module_builder = mb;
409 this.methods = new ArrayList ();
410 this.sources = new Hashtable ();
411 this.orphant_methods = new ArrayList ();
412 this.locals = new ArrayList ();
413 this.mbuilder_array = mbuilder_array;
416 public void Close () {
417 if (assembly == null)
418 assembly = Assembly.LoadFrom (assembly_filename);
422 CreateOutput (assembly);
425 public void CloseNamespace () {
428 // Create and return a new IMonoSymbolDocumentWriter.
429 public ISymbolDocumentWriter DefineDocument (string url,
434 return new MonoSymbolDocumentWriter (url);
437 public void DefineField (
440 FieldAttributes attributes,
442 SymAddressKind addrKind,
447 throw new NotSupportedException ();
450 public void DefineGlobalVariable (
452 FieldAttributes attributes,
454 SymAddressKind addrKind,
459 throw new NotSupportedException ();
462 public void DefineLocalVariable (string name,
463 FieldAttributes attributes,
465 SymAddressKind addrKind,
472 if (current_method == null)
475 current_method.AddLocal (new LocalVariableEntry (name, attributes, signature));
478 public void DefineParameter (string name,
479 ParameterAttributes attributes,
481 SymAddressKind addrKind,
486 throw new NotSupportedException ();
489 public void DefineSequencePoints (ISymbolDocumentWriter document,
496 if (current_method == null)
499 SourceLine source_line = new SourceLine (offsets [0], lines [0], columns [0]);
501 if (current_method != null)
502 current_method.AddLine (source_line);
505 public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
507 throw new NotSupportedException ();
510 public void Initialize (string assembly_filename, string filename, string[] args)
512 this.output_filename = filename;
513 this.assembly_filename = assembly_filename;
516 public void OpenMethod (SymbolToken symbol_token)
518 int token = symbol_token.GetToken ();
520 if ((token & 0xff000000) != 0x06000000)
521 throw new ArgumentException ();
523 int index = (token & 0xffffff) - 1;
525 MethodBase mb = (MethodBase) mbuilder_array [index];
527 current_method = new SourceMethod (mb);
529 methods.Add (current_method);
532 public void SetMethodSourceRange (ISymbolDocumentWriter startDoc,
533 int startLine, int startColumn,
534 ISymbolDocumentWriter endDoc,
535 int endLine, int endColumn)
537 if (current_method == null)
540 if ((startDoc == null) || (endDoc == null))
541 throw new NullReferenceException ();
543 if (!(startDoc is MonoSymbolDocumentWriter) || !(endDoc is MonoSymbolDocumentWriter))
544 throw new NotSupportedException ("both startDoc and endDoc must be of type "
545 + "MonoSymbolDocumentWriter");
547 if (!startDoc.Equals (endDoc))
548 throw new NotSupportedException ("startDoc and endDoc must be the same");
550 string source_file = ((MonoSymbolDocumentWriter) startDoc).FileName;
551 SourceFile source_info;
553 if (sources.ContainsKey (source_file))
554 source_info = (SourceFile) sources [source_file];
556 source_info = new SourceFile (source_file);
557 sources.Add (source_file, source_info);
560 current_method.SetSourceRange (source_info, startLine, startColumn,
563 source_info.AddMethod (current_method);
566 public void CloseMethod () {
567 current_method = null;
570 public void OpenNamespace (string name)
572 throw new NotSupportedException ();
575 public int OpenScope (int startOffset)
577 if (current_method == null)
580 SourceBlock block = new SourceBlock (current_method, startOffset);
581 current_method.StartBlock (block);
586 public void CloseScope (int endOffset) {
587 if (current_method == null)
590 current_method.EndBlock (endOffset);
593 public void SetScopeRange (int scopeID, int startOffset, int endOffset)
595 if (current_method == null)
598 current_method.SetBlockRange (scopeID, startOffset, endOffset);
601 public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
603 throw new NotSupportedException ();
606 public void SetUnderlyingWriter (IntPtr underlyingWriter)
608 throw new NotSupportedException ();
611 public void SetUserEntryPoint (SymbolToken entryMethod)
613 throw new NotSupportedException ();
616 public void UsingNamespace (string fullName)
618 throw new NotSupportedException ();
622 // MonoSymbolWriter implementation
624 protected void DoFixups (Assembly assembly)
626 foreach (SourceMethod method in methods) {
627 if (method._method_base is MethodBuilder) {
628 MethodBuilder mb = (MethodBuilder) method._method_base;
629 method._token = mb.GetToken ().Token;
630 } else if (method._method_base is ConstructorBuilder) {
631 ConstructorBuilder cb = (ConstructorBuilder) method._method_base;
632 method._token = cb.GetToken ().Token;
634 throw new NotSupportedException ();
636 if (method.SourceFile == null)
637 orphant_methods.Add (method);
641 protected void CreateOutput (Assembly assembly)
643 MonoSymbolTableWriter writer = new MonoSymbolTableWriter (output_filename);
644 writer.WriteSymbolTable (this);