//
-// System.Diagnostics.SymbolStore/MonoSymbolWriter.cs
+// Mono.CSharp.Debugger/MonoSymbolWriter.cs
//
// Author:
-// Martin Baulig (martin@gnome.org)
+// Martin Baulig (martin@ximian.com)
//
// This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter
// interface.
// (C) 2002 Ximian, Inc. http://www.ximian.com
//
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
using System;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Diagnostics.SymbolStore;
+using System.Runtime.CompilerServices;
using System.Collections;
using System.IO;
-namespace Mono.CSharp.Debugger
+namespace Mono.CompilerServices.SymbolWriter
{
-
- public class MonoSymbolWriter : IMonoSymbolWriter
+ public interface ISourceFile
{
- protected string output_filename = null;
- protected Hashtable methods = null;
- protected Hashtable sources = null;
-
- protected class SourceInfo
- {
- private MethodInfo[] _methods;
- public readonly string FileName;
-
- public SourceInfo (string filename)
- {
- this.FileName = filename;
-
- this._methods = new MethodInfo [0];
- }
+ SourceFileEntry Entry {
+ get;
+ }
+ }
- public MethodInfo[] GetMethods ()
- {
- return _methods;
- }
+ public interface ISourceMethod
+ {
+ string Name {
+ get;
+ }
- public void AddMethod (MethodInfo method)
- {
- int i = _methods.Length;
- MethodInfo[] new_m = new MethodInfo [i + 1];
- Array.Copy (_methods, new_m, i);
- new_m [i] = method;
- _methods = new_m;
- }
+ int NamespaceID {
+ get;
}
- protected struct MethodInfo
- {
- public MethodInfo (string name, SourceInfo source_file) {
- this.Name = name;
- this.SourceFile = source_file;
- }
+ int Token {
+ get;
+ }
+ }
- public void SetSourceRange (int startLine, int startColumn,
- int endLine, int endColumn)
- {
+ public class MonoSymbolWriter
+ {
+ protected ArrayList locals = null;
+ protected ArrayList methods = null;
+ protected ArrayList sources = null;
+ protected readonly MonoSymbolFile file;
+ private string filename = null;
+
+ LineNumberEntry [] current_method_lines;
+ int current_method_lines_pos = 0;
+
+ internal ISourceFile[] Sources {
+ get {
+ ISourceFile[] retval = new ISourceFile [sources.Count];
+ sources.CopyTo (retval, 0);
+ return retval;
}
-
- public readonly string Name;
- public readonly SourceInfo SourceFile;
}
- protected Object current_method = null;
+ private SourceMethod current_method = null;
//
// Interface IMonoSymbolWriter
//
- public MonoSymbolWriter ()
+ public MonoSymbolWriter (string filename)
{
- methods = new Hashtable ();
- sources = new Hashtable ();
- }
-
- public void Close () {
- CreateDwarfFile (output_filename);
- }
-
- public void CloseNamespace () {
+ this.methods = new ArrayList ();
+ this.sources = new ArrayList ();
+ this.locals = new ArrayList ();
+ this.file = new MonoSymbolFile ();
+
+ this.filename = filename + ".mdb";
+
+ this.current_method_lines = new LineNumberEntry [50];
}
- public void CloseScope (int endOffset) {
- }
+ public void CloseNamespace ()
+ { }
- // Create and return a new IMonoSymbolDocumentWriter.
- public ISymbolDocumentWriter DefineDocument (string url,
- Guid language,
- Guid languageVendor,
- Guid documentType)
+ public void DefineLocalVariable (string name, byte[] signature)
{
- return new MonoSymbolDocumentWriter (url);
- }
+ if (current_method == null)
+ return;
- public void DefineField (
- SymbolToken parent,
- string name,
- FieldAttributes attributes,
- byte[] signature,
- SymAddressKind addrKind,
- int addr1,
- int addr2,
- int addr3)
- {
+ current_method.AddLocal (name, signature);
}
- public void DefineGlobalVariable (
- string name,
- FieldAttributes attributes,
- byte[] signature,
- SymAddressKind addrKind,
- int addr1,
- int addr2,
- int addr3)
+ public void MarkSequencePoint (int offset, int line, int column)
{
- }
+ if (current_method == null)
+ return;
- public void DefineLocalVariable (string name,
- FieldAttributes attributes,
- byte[] signature,
- SymAddressKind addrKind,
- int addr1,
- int addr2,
- int addr3,
- int startOffset,
- int endOffset)
- {
- Console.WriteLine ("WRITE LOCAL: " + name + " " + addr1);
- }
-
- public void DefineParameter (
- string name,
- ParameterAttributes attributes,
- int sequence,
- SymAddressKind addrKind,
- int addr1,
- int addr2,
- int addr3)
- {
+ if (current_method_lines_pos == current_method_lines.Length) {
+ LineNumberEntry [] tmp = current_method_lines;
+ current_method_lines = new LineNumberEntry [current_method_lines.Length * 2];
+ Array.Copy (tmp, current_method_lines, current_method_lines_pos);
+ }
+
+ current_method_lines [current_method_lines_pos++] = new LineNumberEntry (line, offset);
}
- public void DefineSequencePoints (
- ISymbolDocumentWriter document,
- int[] offsets,
- int[] lines,
- int[] columns,
- int[] endLines,
- int[] endColumns)
+ public void OpenMethod (ISourceFile file, ISourceMethod method,
+ int startRow, int startColumn,
+ int endRow, int endColumn)
{
- }
+ SourceMethod source = new SourceMethod (
+ file, method, startRow, startColumn, endRow, endColumn);
- public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
- {
- throw new NotSupportedException ("Please use the 'Initialize (string filename)' "
- + "constructor and read the documentation in "
- + "Mono.CSharp.Debugger/IMonoSymbolWriter.cs");
+ current_method = source;
+ methods.Add (current_method);
}
- // This is documented in IMonoSymbolWriter.cs
- public void Initialize (string filename)
+ public void CloseMethod ()
{
- this.output_filename = filename;
+ current_method.SetLineNumbers (
+ current_method_lines, current_method_lines_pos);
+ current_method_lines_pos = 0;
+
+ current_method = null;
}
- public void OpenMethod (SymbolToken method)
+ public SourceFileEntry DefineDocument (string url)
{
- // do nothing
+ SourceFileEntry entry = new SourceFileEntry (file, url);
+ sources.Add (entry);
+ return entry;
}
- // This is documented in IMonoSymbolWriter.cs
- public void OpenMethod (SymbolToken symbol_token, string name, string source_file)
+ public int DefineNamespace (string name, SourceFileEntry source,
+ string[] using_clauses, int parent)
{
- int token = symbol_token.GetToken ();
- SourceInfo source_info;
-
- if (methods.ContainsKey (token))
- methods.Remove (token);
-
- if (sources.ContainsKey (source_file))
- source_info = (SourceInfo) sources [source_file];
- else {
- source_info = new SourceInfo (source_file);
- sources.Add (source_file, source_info);
- }
-
- current_method = new MethodInfo (name, source_info);
-
- source_info.AddMethod ((MethodInfo) current_method);
-
- methods.Add (token, current_method);
+ if ((source == null) || (using_clauses == null))
+ throw new NullReferenceException ();
- OpenMethod (symbol_token);
+ return source.DefineNamespace (name, using_clauses, parent);
}
- public void SetMethodSourceRange (ISymbolDocumentWriter startDoc,
- int startLine, int startColumn,
- ISymbolDocumentWriter endDoc,
- int endLine, int endColumn)
+ public int OpenScope (int startOffset)
{
- if ((startDoc == null) || (endDoc == null))
- throw new NullReferenceException ();
-
- if (!(startDoc is MonoSymbolDocumentWriter) || !(endDoc is MonoSymbolDocumentWriter))
- throw new NotSupportedException ("both startDoc and endDoc must be of type "
- + "MonoSymbolDocumentWriter");
-
- if (!startDoc.Equals (endDoc))
- throw new NotSupportedException ("startDoc and endDoc must be the same");
+ if (current_method == null)
+ return 0;
- if (current_method != null)
- ((MethodInfo) current_method).SetSourceRange (startLine, startColumn,
- endLine, endColumn);
+ current_method.StartBlock (startOffset);
+ return 0;
}
- public void CloseMethod () {
- current_method = null;
- }
-
- public void OpenNamespace (string name)
+ public void CloseScope (int endOffset)
{
- }
+ if (current_method == null)
+ return;
- public int OpenScope (int startOffset)
- {
- throw new NotImplementedException ();
+ current_method.EndBlock (endOffset);
}
- public void SetScopeRange (int scopeID, int startOffset, int endOffset)
+ protected byte[] CreateOutput (Guid guid)
{
- }
+ foreach (SourceMethod method in methods) {
+ method.SourceFile.Entry.DefineMethod (
+ method.Method.Name, method.Method.Token,
+ method.Locals, method.Lines, method.Blocks,
+ method.Start.Row, method.End.Row,
+ method.Method.NamespaceID);
+ }
- public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
- {
+ return file.CreateSymbolFile (guid);
}
- public void SetUnderlyingWriter (IntPtr underlyingWriter)
+ public void WriteSymbolFile (Guid guid)
{
+ using (FileStream stream = new FileStream (
+ filename, FileMode.Create, FileAccess.Write)) {
+ byte[] data = CreateOutput (guid);
+ stream.Write (data, 0, data.Length);
+ }
}
- public void SetUserEntryPoint (SymbolToken entryMethod)
+ protected class SourceMethod
{
- }
+ LineNumberEntry [] lines;
+ private ArrayList _locals;
+ private ArrayList _blocks;
+ private Stack _block_stack;
+ private int next_block_id = 0;
+ private ISourceMethod _method;
+ private ISourceFile _file;
+ private LineNumberEntry _start, _end;
+
+ private LexicalBlockEntry _implicit_block;
+
+ public SourceMethod (ISourceFile file, ISourceMethod method,
+ int startLine, int startColumn,
+ int endLine, int endColumn)
+ {
+ this._file = file;
+ this._method = method;
- public void UsingNamespace (string fullName)
- {
- }
+ this._start = new LineNumberEntry (startLine, 0);
+ this._end = new LineNumberEntry (endLine, 0);
- //
- // MonoSymbolWriter implementation
- //
- protected void WriteMethod (DwarfFileWriter.DieCompileUnit parent_die, MethodInfo method)
- {
- Console.WriteLine ("WRITING METHOD: " + method.Name);
+ this._implicit_block = new LexicalBlockEntry (0, 0);
+ }
- DwarfFileWriter.DieSubProgram die;
+ public void StartBlock (int startOffset)
+ {
+ LexicalBlockEntry block = new LexicalBlockEntry (
+ ++next_block_id, startOffset);
+ if (_block_stack == null)
+ _block_stack = new Stack ();
+ _block_stack.Push (block);
+ if (_blocks == null)
+ _blocks = new ArrayList ();
+ _blocks.Add (block);
+ }
- die = new DwarfFileWriter.DieSubProgram (parent_die, method.Name);
- }
+ public void EndBlock (int endOffset)
+ {
+ LexicalBlockEntry block =
+ (LexicalBlockEntry) _block_stack.Pop ();
- protected void WriteSource (DwarfFileWriter writer, SourceInfo source)
- {
- Console.WriteLine ("WRITING SOURCE: " + source.FileName);
+ block.Close (endOffset);
+ }
- DwarfFileWriter.CompileUnit compile_unit = new DwarfFileWriter.CompileUnit (
- writer, source.FileName);
+ public LexicalBlockEntry[] Blocks {
+ get {
+ if (_blocks == null)
+ return new LexicalBlockEntry [0];
+ else {
+ LexicalBlockEntry[] retval =
+ new LexicalBlockEntry [_blocks.Count];
+ _blocks.CopyTo (retval, 0);
+ return retval;
+ }
+ }
+ }
- DwarfFileWriter.DieCompileUnit die = new DwarfFileWriter.DieCompileUnit (compile_unit);
+ public LexicalBlockEntry CurrentBlock {
+ get {
+ if ((_block_stack != null) && (_block_stack.Count > 0))
+ return (LexicalBlockEntry) _block_stack.Peek ();
+ else
+ return _implicit_block;
+ }
+ }
- foreach (MethodInfo method in source.GetMethods ())
- WriteMethod (die, method);
- }
+ public LineNumberEntry[] Lines {
+ get {
+ return lines;
+ }
+ }
- protected void CreateDwarfFile (string filename)
- {
- Console.WriteLine ("WRITING DWARF FILE: " + filename);
+ public LocalVariableEntry[] Locals {
+ get {
+ if (_locals == null)
+ return new LocalVariableEntry [0];
+ else {
+ LocalVariableEntry[] retval =
+ new LocalVariableEntry [_locals.Count];
+ _locals.CopyTo (retval, 0);
+ return retval;
+ }
+ }
+ }
- DwarfFileWriter writer = new DwarfFileWriter (filename);
+ public void AddLocal (string name, byte[] signature)
+ {
+ if (_locals == null)
+ _locals = new ArrayList ();
+ _locals.Add (new LocalVariableEntry (
+ name, signature, CurrentBlock.Index));
+ }
- foreach (SourceInfo source in sources.Values)
- WriteSource (writer, source);
+ public ISourceFile SourceFile {
+ get { return _file; }
+ }
- writer.Close ();
+ public ISourceMethod Method {
+ get { return _method; }
+ }
- Console.WriteLine ("DONE WRITING DWARF FILE");
+ public LineNumberEntry Start {
+ get { return _start; }
+ }
+
+ public LineNumberEntry End {
+ get { return _end; }
+ }
+ //
+ // Passes on the lines from the MonoSymbolWriter. This method is
+ // free to mutate the lns array, and it does.
+ //
+ internal void SetLineNumbers (LineNumberEntry [] lns, int count)
+ {
+ int pos = 0;
+
+ int last_offset = -1;
+ int last_row = -1;
+ for (int i = 0; i < count; i++) {
+ LineNumberEntry line = lns [i];
+
+ if (line.Offset > last_offset) {
+ if (last_row >= 0)
+ lns [pos++] = new LineNumberEntry (
+ last_row, last_offset);
+
+ last_row = line.Row;
+ last_offset = line.Offset;
+ } else if (line.Row > last_row) {
+ last_row = line.Row;
+ }
+ }
+
+ lines = new LineNumberEntry [count + ((last_row >= 0) ? 1 : 0)];
+ Array.Copy (lns, lines, pos);
+ if (last_row >= 0)
+ lines [pos] = new LineNumberEntry (
+ last_row, last_offset);
+ }
}
}
}