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
24 public class MonoSymbolWriter : IMonoSymbolWriter
26 protected Assembly assembly;
27 protected string output_filename = null;
28 protected ArrayList locals = null;
29 protected ArrayList orphant_methods = null;
30 protected Hashtable methods = null;
31 protected Hashtable sources = null;
33 protected class SourceFile : ISourceFile
35 private ArrayList _methods = new ArrayList ();
36 private string _file_name;
38 public SourceFile (string filename)
40 this._file_name = filename;
43 public override string ToString ()
48 // interface ISourceFile
50 public string FileName {
56 public ISourceMethod[] Methods {
58 ISourceMethod[] retval = new ISourceMethod [_methods.Count];
59 _methods.CopyTo (retval);
64 public void AddMethod (ISourceMethod method)
66 _methods.Add (method);
70 protected class SourceBlock : ISourceBlock
72 static private int next_index;
73 private readonly int _index;
75 public SourceBlock (ISourceMethod method, ISourceLine start, ISourceLine end)
77 this._method = method;
80 this._index = ++next_index;
83 internal SourceBlock (ISourceMethod method, int startOffset)
85 this._method = method;
86 this._start = new SourceLine (startOffset);
87 this._index = ++next_index;
90 public override string ToString ()
92 return "SourceBlock #" + ID + " (" + Start + " - " + End + ")";
95 private readonly ISourceMethod _method;
96 internal ISourceLine _start;
97 internal ISourceLine _end;
99 private ArrayList _locals = new ArrayList ();
101 public ISourceMethod SourceMethod {
107 public ISourceLine Start {
113 public ISourceLine End {
125 public ILocalVariable[] Locals {
127 ILocalVariable[] retval = new ILocalVariable [_locals.Count];
128 _locals.CopyTo (retval);
133 public void AddLocal (ILocalVariable local)
139 protected class SourceLine : ISourceLine
141 public SourceLine (int row, int column)
142 : this (0, row, column)
144 this._type = SourceOffsetType.OFFSET_NONE;
147 public SourceLine (int offset, int row, int column)
149 this._offset = offset;
151 this._column = column;
152 this._type = SourceOffsetType.OFFSET_IL;
155 internal SourceLine (int offset)
156 : this (offset, 0, 0)
159 public override string ToString ()
161 return "SourceLine (" + _offset + "," + _row + ":" + _column + ")";
164 internal SourceOffsetType _type;
165 internal int _offset;
167 internal int _column;
169 // interface ISourceLine
171 public SourceOffsetType OffsetType {
196 protected class LocalVariable : ILocalVariable
198 public LocalVariable (string name, byte[] signature, int token, int index)
199 : this (name, signature, token, index, null)
202 public LocalVariable (string name, byte[] signature, int token, int index,
206 this._signature = signature;
212 private readonly string _name;
214 private readonly byte[] _signature;
215 private readonly int _token;
216 private readonly int _index;
217 private readonly ISourceLine _line;
219 public override string ToString ()
221 return "LocalVariable (" + _index + "," + _name + ")";
224 // interface ILocalVariable
250 public byte[] Signature {
256 public ISourceLine Line {
263 protected class SourceMethod : ISourceMethod
265 private ArrayList _lines = new ArrayList ();
266 private ArrayList _blocks = new ArrayList ();
267 private Hashtable _block_hash = new Hashtable ();
268 private Stack _block_stack = new Stack ();
270 internal MethodInfo _method_info;
271 internal ISourceFile _source_file;
272 private readonly int _token;
274 private SourceBlock _implicit_block;
276 public SourceMethod (int token, MethodInfo method_info, ISourceFile source_file)
279 this._method_info = method_info;
280 this._source_file = source_file;
283 internal SourceMethod (int token)
287 this._implicit_block = new SourceBlock (this, 0);
290 public void SetSourceRange (ISourceFile sourceFile,
291 int startLine, int startColumn,
292 int endLine, int endColumn)
294 _source_file = sourceFile;
295 _implicit_block._start = new SourceLine (startLine, startColumn);
296 _implicit_block._end = new SourceLine (endLine, endColumn);
300 public void StartBlock (ISourceBlock block)
302 _block_stack.Push (block);
305 public void EndBlock (int endOffset) {
306 SourceBlock block = (SourceBlock) _block_stack.Pop ();
308 block._end = new SourceLine (endOffset);
310 _block_hash.Add (block.ID, block);
313 public void SetBlockRange (int BlockID, int startOffset, int endOffset)
315 SourceBlock block = (SourceBlock) _block_hash [BlockID];
316 ((SourceLine) block.Start)._offset = startOffset;
317 ((SourceLine) block.End)._offset = endOffset;
320 public ISourceBlock CurrentBlock {
322 if (_block_stack.Count > 0)
323 return (ISourceBlock) _block_stack.Peek ();
325 return _implicit_block;
329 // interface ISourceMethod
331 public ISourceLine[] Lines {
333 ISourceLine[] retval = new ISourceLine [_lines.Count];
334 _lines.CopyTo (retval);
339 public void AddLine (ISourceLine line)
344 public ISourceBlock[] Blocks {
346 ISourceBlock[] retval = new ISourceBlock [_blocks.Count];
347 _blocks.CopyTo (retval);
352 public ILocalVariable[] Locals {
354 return _implicit_block.Locals;
358 public void AddLocal (ILocalVariable local)
360 _implicit_block.AddLocal (local);
363 public MethodInfo MethodInfo {
369 public ISourceFile SourceFile {
381 public ISourceLine Start {
383 return _implicit_block.Start;
387 public ISourceLine End {
389 return _implicit_block.End;
394 protected SourceMethod current_method = null;
395 private readonly string assembly_filename = null;
398 // Interface IMonoSymbolWriter
401 public MonoSymbolWriter (string filename)
403 this.assembly_filename = filename;
405 this.methods = new Hashtable ();
406 this.sources = new Hashtable ();
407 this.orphant_methods = new ArrayList ();
408 this.locals = new ArrayList ();
411 public void Close () {
412 if (assembly == null)
413 assembly = AppDomain.CurrentDomain.Load (assembly_filename);
417 CreateDwarfFile (output_filename);
420 public void CloseNamespace () {
423 // Create and return a new IMonoSymbolDocumentWriter.
424 public ISymbolDocumentWriter DefineDocument (string url,
429 return new MonoSymbolDocumentWriter (url);
432 public void DefineField (
435 FieldAttributes attributes,
437 SymAddressKind addrKind,
444 public void DefineGlobalVariable (
446 FieldAttributes attributes,
448 SymAddressKind addrKind,
455 public void DefineLocalVariable (string name,
456 FieldAttributes attributes,
458 SymAddressKind addrKind,
465 if (current_method == null)
468 int token = current_method.Token;
470 LocalVariable local_info = new LocalVariable (name, signature, token, addr1);
472 current_method.CurrentBlock.AddLocal (local_info);
473 locals.Add (local_info);
476 public void DefineParameter (string name,
477 ParameterAttributes attributes,
479 SymAddressKind addrKind,
484 throw new NotSupportedException ();
487 public void DefineSequencePoints (ISymbolDocumentWriter document,
494 SourceLine source_line = new SourceLine (offsets [0], lines [0], columns [0]);
496 if (current_method != null)
497 current_method.AddLine (source_line);
500 public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
502 this.output_filename = filename;
505 public void OpenMethod (SymbolToken symbol_token)
507 int token = symbol_token.GetToken ();
509 if (methods.ContainsKey (token))
510 methods.Remove (token);
512 current_method = new SourceMethod (token);
514 methods.Add (token, current_method);
517 public void SetMethodSourceRange (ISymbolDocumentWriter startDoc,
518 int startLine, int startColumn,
519 ISymbolDocumentWriter endDoc,
520 int endLine, int endColumn)
522 if (current_method == null)
525 if ((startDoc == null) || (endDoc == null))
526 throw new NullReferenceException ();
528 if (!(startDoc is MonoSymbolDocumentWriter) || !(endDoc is MonoSymbolDocumentWriter))
529 throw new NotSupportedException ("both startDoc and endDoc must be of type "
530 + "MonoSymbolDocumentWriter");
532 if (!startDoc.Equals (endDoc))
533 throw new NotSupportedException ("startDoc and endDoc must be the same");
535 string source_file = ((MonoSymbolDocumentWriter) startDoc).FileName;
536 SourceFile source_info;
538 if (sources.ContainsKey (source_file))
539 source_info = (SourceFile) sources [source_file];
541 source_info = new SourceFile (source_file);
542 sources.Add (source_file, source_info);
545 current_method.SetSourceRange (source_info, startLine, startColumn,
548 source_info.AddMethod (current_method);
551 public void CloseMethod () {
552 current_method = null;
555 public void OpenNamespace (string name)
559 public int OpenScope (int startOffset)
561 if (current_method == null)
564 ISourceBlock block = new SourceBlock (current_method, startOffset);
565 current_method.StartBlock (block);
570 public void CloseScope (int endOffset) {
571 if (current_method == null)
574 current_method.EndBlock (endOffset);
577 public void SetScopeRange (int scopeID, int startOffset, int endOffset)
579 if (current_method == null)
582 current_method.SetBlockRange (scopeID, startOffset, endOffset);
585 public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
589 public void SetUnderlyingWriter (IntPtr underlyingWriter)
591 throw new NotSupportedException ();
594 public void SetUserEntryPoint (SymbolToken entryMethod)
598 public void UsingNamespace (string fullName)
603 // MonoSymbolWriter implementation
605 protected void WriteLocal (DwarfFileWriter.Die parent_die, ILocalVariable local)
607 DwarfFileWriter.DieMethodVariable die;
609 die = new DwarfFileWriter.DieMethodVariable (parent_die, local);
612 protected void WriteBlock (DwarfFileWriter.Die parent_die, ISourceBlock block)
614 DwarfFileWriter.DieLexicalBlock die;
616 die = new DwarfFileWriter.DieLexicalBlock (parent_die, block);
618 foreach (ILocalVariable local in block.Locals)
619 WriteLocal (die, local);
622 protected void WriteMethod (DwarfFileWriter.DieCompileUnit parent_die, ISourceMethod method)
624 DwarfFileWriter.DieSubProgram die;
626 die = new DwarfFileWriter.DieSubProgram (parent_die, method);
628 foreach (ILocalVariable local in method.Locals)
629 WriteLocal (die, local);
631 foreach (ISourceBlock block in method.Blocks)
632 WriteBlock (die, block);
635 protected void WriteSource (DwarfFileWriter writer, ISourceFile source)
637 DwarfFileWriter.CompileUnit compile_unit = new DwarfFileWriter.CompileUnit (
638 writer, source.FileName);
640 DwarfFileWriter.DieCompileUnit die = new DwarfFileWriter.DieCompileUnit (compile_unit);
642 foreach (ISourceMethod method in source.Methods)
643 WriteMethod (die, method);
647 [MethodImplAttribute(MethodImplOptions.InternalCall)]
648 internal extern static Type get_local_type_from_sig (Assembly module, byte[] sig);
650 [MethodImplAttribute(MethodImplOptions.InternalCall)]
651 internal extern static MethodInfo get_method (Assembly module, int token);
653 protected void DoFixups (Assembly assembly)
655 foreach (SourceMethod method in methods.Values) {
656 method._method_info = get_method (assembly, method.Token);
658 if (method.SourceFile == null)
659 orphant_methods.Add (method);
662 foreach (LocalVariable local in locals) {
663 byte[] signature = local.Signature;
665 Type type = get_local_type_from_sig (assembly, signature);
667 ((LocalVariable) local)._type = type;
671 protected void CreateDwarfFile (string filename)
673 DwarfFileWriter writer = new DwarfFileWriter (filename);
675 foreach (ISourceFile source in sources.Values)
676 WriteSource (writer, source);
678 if (orphant_methods.Count > 0) {
679 SourceFile source = new SourceFile ("<unknown>");
681 foreach (SourceMethod orphant in orphant_methods) {
682 orphant._source_file = source;
683 source.AddMethod (orphant);
686 WriteSource (writer, source);