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.Diagnostics.SymbolStore;
17 using System.Collections;
20 namespace Mono.CSharp.Debugger
23 public class MonoSymbolWriter : IMonoSymbolWriter
25 protected string output_filename = null;
26 protected Hashtable methods = null;
27 protected Hashtable sources = null;
29 protected class SourceFile : ISourceFile
31 private ArrayList _methods = new ArrayList ();
32 private string _file_name;
34 public SourceFile (string filename)
36 this._file_name = filename;
39 public override string ToString ()
44 // interface ISourceFile
46 public string FileName {
52 public ISourceMethod[] Methods {
54 ISourceMethod[] retval = new ISourceMethod [_methods.Count];
55 _methods.CopyTo (retval);
60 public void AddMethod (ISourceMethod method)
62 _methods.Add (method);
66 protected class SourceBlock : ISourceBlock
68 static private int next_index;
69 private readonly int _index;
71 public SourceBlock (ISourceMethod method, ISourceLine start, ISourceLine end)
73 this._method = method;
76 this._index = ++next_index;
79 internal SourceBlock (ISourceMethod method, int startOffset)
81 this._method = method;
82 this._start = new SourceLine (startOffset);
83 this._index = ++next_index;
86 public override string ToString ()
88 return "SourceBlock #" + ID + " (" + Start + " - " + End + ")";
91 private readonly ISourceMethod _method;
92 internal ISourceLine _start;
93 internal ISourceLine _end;
95 private ArrayList _locals = new ArrayList ();
97 public ISourceMethod SourceMethod {
103 public ISourceLine Start {
109 public ISourceLine End {
121 public ILocalVariable[] Locals {
123 ILocalVariable[] retval = new ILocalVariable [_locals.Count];
124 _locals.CopyTo (retval);
129 public void AddLocal (ILocalVariable local)
135 protected class SourceLine : ISourceLine
137 public SourceLine (int row, int column)
138 : this (0, row, column)
140 this._type = SourceOffsetType.OFFSET_NONE;
143 public SourceLine (int offset, int row, int column)
145 this._offset = offset;
147 this._column = column;
148 this._type = SourceOffsetType.OFFSET_IL;
151 internal SourceLine (int offset)
152 : this (offset, 0, 0)
155 public override string ToString ()
157 return "SourceLine (" + _offset + "," + _row + ":" + _column + ")";
160 internal SourceOffsetType _type;
161 internal int _offset;
163 internal int _column;
165 // interface ISourceLine
167 public SourceOffsetType OffsetType {
192 protected class LocalVariable : ILocalVariable
194 public LocalVariable (string name, Type type, int token, int index)
195 : this (name, type, token, index, null)
198 public LocalVariable (string name, Type type, int token, int index,
208 private readonly string _name;
209 private readonly Type _type;
210 private readonly int _token;
211 private readonly int _index;
212 private readonly ISourceLine _line;
214 public override string ToString ()
216 return "LocalVariable (" + _index + "," + _name + ")";
219 // interface ILocalVariable
245 public ISourceLine Line {
252 protected class SourceMethod : ISourceMethod
254 private ArrayList _lines = new ArrayList ();
255 private ArrayList _blocks = new ArrayList ();
256 private Hashtable _block_hash = new Hashtable ();
257 private Stack _block_stack = new Stack ();
259 private readonly MethodInfo _method_info;
260 private readonly SourceFile _source_file;
261 private readonly int _token;
263 private SourceBlock _implicit_block;
265 public SourceMethod (int token, MethodInfo method_info, SourceFile source_file) {
266 this._method_info = method_info;
267 this._source_file = source_file;
270 this._implicit_block = new SourceBlock (this, 0);
273 public void SetSourceRange (int startLine, int startColumn,
274 int endLine, int endColumn)
276 Console.WriteLine ("SOURCE RANGE: " + MethodInfo.Name + " " +
277 startLine + ":" + startColumn + " " +
278 endLine + ":" + endColumn);
280 _implicit_block._start = new SourceLine (startLine, startColumn);
281 _implicit_block._end = new SourceLine (endLine, endColumn);
285 public void StartBlock (ISourceBlock block)
287 _block_stack.Push (block);
290 public void EndBlock (int endOffset) {
291 SourceBlock block = (SourceBlock) _block_stack.Pop ();
293 block._end = new SourceLine (endOffset);
295 _block_hash.Add (block.ID, block);
298 public void SetBlockRange (int BlockID, int startOffset, int endOffset)
300 SourceBlock block = (SourceBlock) _block_hash [BlockID];
301 ((SourceLine) block.Start)._offset = startOffset;
302 ((SourceLine) block.End)._offset = endOffset;
305 public ISourceBlock CurrentBlock {
307 if (_block_stack.Count > 0)
308 return (ISourceBlock) _block_stack.Peek ();
310 return _implicit_block;
314 // interface ISourceMethod
316 public ISourceLine[] Lines {
318 ISourceLine[] retval = new ISourceLine [_lines.Count];
319 _lines.CopyTo (retval);
324 public void AddLine (ISourceLine line)
329 public ISourceBlock[] Blocks {
331 ISourceBlock[] retval = new ISourceBlock [_blocks.Count];
332 _blocks.CopyTo (retval);
337 public ILocalVariable[] Locals {
339 return _implicit_block.Locals;
343 public void AddLocal (ILocalVariable local)
345 _implicit_block.AddLocal (local);
348 public MethodInfo MethodInfo {
354 public ISourceFile SourceFile {
366 public ISourceLine Start {
368 return _implicit_block.Start;
372 public ISourceLine End {
374 return _implicit_block.End;
379 protected SourceMethod current_method = null;
382 // Interface IMonoSymbolWriter
385 public MonoSymbolWriter ()
387 methods = new Hashtable ();
388 sources = new Hashtable ();
391 public void Close () {
392 CreateDwarfFile (output_filename);
395 public void CloseNamespace () {
398 // Create and return a new IMonoSymbolDocumentWriter.
399 public ISymbolDocumentWriter DefineDocument (string url,
404 return new MonoSymbolDocumentWriter (url);
407 public void DefineField (
410 FieldAttributes attributes,
412 SymAddressKind addrKind,
419 public void DefineGlobalVariable (
421 FieldAttributes attributes,
423 SymAddressKind addrKind,
430 public void DefineLocalVariable (string name,
431 FieldAttributes attributes,
433 SymAddressKind addrKind,
440 if (current_method == null)
443 int token = current_method.Token;
445 LocalVariable local_info = new LocalVariable (name, typeof (int), token, addr1);
447 current_method.CurrentBlock.AddLocal (local_info);
450 public void DefineParameter (
452 ParameterAttributes attributes,
454 SymAddressKind addrKind,
461 public void DefineSequencePoints (ISymbolDocumentWriter document,
468 SourceLine source_line = new SourceLine (offsets [0], lines [0], columns [0]);
470 if (current_method != null)
471 current_method.AddLine (source_line);
474 public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
476 throw new NotSupportedException ("Please use the 'Initialize (string filename)' "
477 + "constructor and read the documentation in "
478 + "Mono.CSharp.Debugger/IMonoSymbolWriter.cs");
481 // This is documented in IMonoSymbolWriter.cs
482 public void Initialize (string filename)
484 this.output_filename = filename;
487 public void OpenMethod (SymbolToken method)
492 // This is documented in IMonoSymbolWriter.cs
493 public void OpenMethod (SymbolToken symbol_token, MethodInfo method_info,
496 int token = symbol_token.GetToken ();
497 SourceFile source_info;
499 if (methods.ContainsKey (token))
500 methods.Remove (token);
502 if (sources.ContainsKey (source_file))
503 source_info = (SourceFile) sources [source_file];
505 source_info = new SourceFile (source_file);
506 sources.Add (source_file, source_info);
509 current_method = new SourceMethod (token, method_info, source_info);
511 source_info.AddMethod (current_method);
513 methods.Add (token, current_method);
515 OpenMethod (symbol_token);
518 public void SetMethodSourceRange (ISymbolDocumentWriter startDoc,
519 int startLine, int startColumn,
520 ISymbolDocumentWriter endDoc,
521 int endLine, int endColumn)
523 if ((startDoc == null) || (endDoc == null))
524 throw new NullReferenceException ();
526 if (!(startDoc is MonoSymbolDocumentWriter) || !(endDoc is MonoSymbolDocumentWriter))
527 throw new NotSupportedException ("both startDoc and endDoc must be of type "
528 + "MonoSymbolDocumentWriter");
530 if (!startDoc.Equals (endDoc))
531 throw new NotSupportedException ("startDoc and endDoc must be the same");
533 if (current_method != null)
534 current_method.SetSourceRange (startLine, startColumn,
538 public void CloseMethod () {
539 current_method = null;
542 public void OpenNamespace (string name)
546 public int OpenScope (int startOffset)
548 if (current_method == null)
551 ISourceBlock block = new SourceBlock (current_method, startOffset);
552 current_method.StartBlock (block);
557 public void CloseScope (int endOffset) {
558 if (current_method == null)
561 current_method.EndBlock (endOffset);
564 public void SetScopeRange (int scopeID, int startOffset, int endOffset)
566 if (current_method == null)
569 current_method.SetBlockRange (scopeID, startOffset, endOffset);
572 public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
576 public void SetUnderlyingWriter (IntPtr underlyingWriter)
580 public void SetUserEntryPoint (SymbolToken entryMethod)
584 public void UsingNamespace (string fullName)
589 // MonoSymbolWriter implementation
591 protected void WriteLocal (DwarfFileWriter.Die parent_die, ILocalVariable local)
593 DwarfFileWriter.DieMethodVariable die;
595 Console.WriteLine ("WRITE LOCAL: " + (LocalVariable) local);
597 die = new DwarfFileWriter.DieMethodVariable (parent_die, local);
600 protected void WriteBlock (DwarfFileWriter.Die parent_die, ISourceBlock block)
602 DwarfFileWriter.DieLexicalBlock die;
604 Console.WriteLine ("WRITE BLOCK: " + (SourceBlock) block);
606 die = new DwarfFileWriter.DieLexicalBlock (parent_die, block);
608 foreach (ILocalVariable local in block.Locals)
609 WriteLocal (die, local);
612 protected void WriteMethod (DwarfFileWriter.DieCompileUnit parent_die, ISourceMethod method)
614 DwarfFileWriter.DieSubProgram die;
616 die = new DwarfFileWriter.DieSubProgram (parent_die, method);
618 Console.WriteLine ("WRITE METHOD: " + method.MethodInfo.Name);
620 foreach (ILocalVariable local in method.Locals)
621 WriteLocal (die, local);
623 foreach (ISourceBlock block in method.Blocks)
624 WriteBlock (die, block);
627 protected void WriteSource (DwarfFileWriter writer, ISourceFile source)
629 DwarfFileWriter.CompileUnit compile_unit = new DwarfFileWriter.CompileUnit (
630 writer, source.FileName);
632 DwarfFileWriter.DieCompileUnit die = new DwarfFileWriter.DieCompileUnit (compile_unit);
634 foreach (ISourceMethod method in source.Methods)
635 WriteMethod (die, method);
638 protected void CreateDwarfFile (string filename)
640 DwarfFileWriter writer = new DwarfFileWriter (filename);
642 foreach (ISourceFile source in sources.Values)
643 WriteSource (writer, source);