//
-// 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.Runtime.CompilerServices;
-using System.Diagnostics.SymbolStore;
using System.Collections;
using System.IO;
-namespace Mono.CSharp.Debugger
+namespace Mono.CompilerServices.SymbolWriter
{
- internal class SourceFile : SourceFileEntry, ISymbolDocumentWriter
+ public interface ISourceFile
{
- private ArrayList _methods = new ArrayList ();
-
- public SourceFile (MonoSymbolFile file, string filename)
- : base (file, filename)
- { }
-
- public new SourceMethod[] Methods {
- get {
- SourceMethod[] retval = new SourceMethod [_methods.Count];
- _methods.CopyTo (retval);
- return retval;
- }
- }
-
- public void AddMethod (SourceMethod method)
- {
- _methods.Add (method);
- }
-
- void ISymbolDocumentWriter.SetCheckSum (Guid algorithmId, byte[] checkSum)
- {
- throw new NotSupportedException ();
- }
-
- void ISymbolDocumentWriter.SetSource (byte[] source)
- {
- throw new NotSupportedException ();
+ SourceFileEntry Entry {
+ get;
}
}
- internal class SourceMethod
+ public interface ISourceMethod
{
- LineNumberEntry [] lines;
- private ArrayList _locals;
- private ArrayList _blocks;
- private Stack _block_stack;
- private int next_block_id = 0;
-
- internal readonly MethodBase _method_base;
- internal SourceFile _source_file;
- internal int _token;
- private int _namespace_id;
- private LineNumberEntry _start, _end;
- private MonoSymbolFile _file;
-
- private LexicalBlockEntry _implicit_block;
-
- internal SourceMethod (MonoSymbolFile file, SourceFile source_file,
- int startLine, int startColumn, int endLine, int endColumn,
- MethodBase method_base, int namespace_id)
- {
- this._file = file;
- this._method_base = method_base;
- this._source_file = source_file;
- this._namespace_id = namespace_id;
-
- this._start = new LineNumberEntry (startLine, 0);
- this._end = new LineNumberEntry (endLine, 0);
-
- this._implicit_block = new LexicalBlockEntry (0, 0);
- }
-
- 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);
+ string Name {
+ get;
}
- public void EndBlock (int endOffset)
- {
- LexicalBlockEntry block = (LexicalBlockEntry) _block_stack.Pop ();
-
- block.Close (endOffset);
- }
-
- public LexicalBlockEntry[] Blocks {
- get {
- if (_blocks == null)
- return new LexicalBlockEntry [0];
- else {
- LexicalBlockEntry[] retval = new LexicalBlockEntry [_blocks.Count];
- _blocks.CopyTo (retval, 0);
- return retval;
- }
- }
- }
-
- public LexicalBlockEntry CurrentBlock {
- get {
- if ((_block_stack != null) && (_block_stack.Count > 0))
- return (LexicalBlockEntry) _block_stack.Peek ();
- else
- return _implicit_block;
- }
+ int NamespaceID {
+ get;
}
- public LineNumberEntry[] Lines {
- get {
- return lines;
- }
- }
-
- static LocalVariableEntry [] locals_buf = new LocalVariableEntry [20];
- int locals_pos = 0;
-
- public LocalVariableEntry[] Locals {
- get {
- if (locals_pos == 0)
- return new LocalVariableEntry [0];
- else {
- LocalVariableEntry[] retval = new LocalVariableEntry [locals_pos];
- Array.Copy (locals_buf, retval, locals_pos);
- return retval;
- }
- }
- }
-
- public void AddLocal (string name, FieldAttributes attributes, byte[] signature)
- {
- if (locals_pos == locals_buf.Length) {
- LocalVariableEntry [] t = new LocalVariableEntry [locals_buf.Length * 2 + 1];
- Array.Copy (locals_buf, t, locals_pos);
- locals_buf = t;
- }
- locals_buf [locals_pos ++] = new LocalVariableEntry (name, attributes, signature, CurrentBlock.Index);
- }
-
- public MethodBase MethodBase {
- get {
- return _method_base;
- }
- }
-
- public string FullName {
- get {
- return _method_base.DeclaringType.FullName + "." + _method_base.Name;
- }
- }
-
- public Type ReturnType {
- get {
- if (_method_base is MethodInfo)
- return ((MethodInfo)_method_base).ReturnType;
- else if (_method_base is ConstructorInfo)
- return _method_base.DeclaringType;
- else
- throw new NotSupportedException ();
- }
- }
-
- public ParameterInfo[] Parameters {
- get {
- if (_method_base == null)
- return new ParameterInfo [0];
-
- ParameterInfo [] retval = _method_base.GetParameters ();
- if (retval == null)
- return new ParameterInfo [0];
- else
- return retval;
- }
- }
-
- public SourceFile SourceFile {
- get {
- return _source_file;
- }
- }
-
- public int Token {
- get {
- if (_token != 0)
- return _token;
- else
- throw new NotSupportedException ();
- }
- }
-
- public bool HasSource {
- get {
- return _source_file != null;
- }
- }
-
- public LineNumberEntry Start {
- get {
- return _start;
- }
- }
-
- public LineNumberEntry End {
- get {
- return _end;
- }
- }
-
- public int NamespaceID {
- get {
- return _namespace_id;
- }
- }
-
- //
- // 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);
+ int Token {
+ get;
}
}
- public class MonoSymbolWriter : IMonoSymbolWriter
+ public class MonoSymbolWriter
{
- protected ModuleBuilder module_builder;
protected ArrayList locals = null;
- protected ArrayList orphant_methods = null;
protected ArrayList methods = null;
- protected Hashtable sources = null;
- private MonoSymbolFile file = null;
+ protected ArrayList sources = null;
+ protected readonly MonoSymbolFile file;
+ private string filename = null;
LineNumberEntry [] current_method_lines;
int current_method_lines_pos = 0;
- internal SourceMethod[] Methods {
- get {
- SourceMethod[] retval = new SourceMethod [methods.Count];
- methods.CopyTo (retval);
- return retval;
- }
- }
-
- internal SourceFile[] Sources {
+ internal ISourceFile[] Sources {
get {
- SourceFile[] retval = new SourceFile [sources.Count];
- sources.Values.CopyTo (retval, 0);
+ ISourceFile[] retval = new ISourceFile [sources.Count];
+ sources.CopyTo (retval, 0);
return retval;
}
}
// Interface IMonoSymbolWriter
//
- public MonoSymbolWriter (ModuleBuilder mb)
+ public MonoSymbolWriter (string filename)
{
- this.module_builder = mb;
this.methods = new ArrayList ();
- this.sources = new Hashtable ();
- this.orphant_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 Close ()
- {
- throw new InvalidOperationException ();
- }
-
- public byte[] CreateSymbolFile (AssemblyBuilder assembly_builder)
- {
- DoFixups (assembly_builder);
-
- return CreateOutput (assembly_builder);
- }
-
- public void CloseNamespace () {
- }
-
- // Create and return a new IMonoSymbolDocumentWriter.
- public ISymbolDocumentWriter DefineDocument (string url,
- Guid language,
- Guid languageVendor,
- Guid documentType)
- {
- if (sources.ContainsKey (url))
- return (ISymbolDocumentWriter)sources [url];
- SourceFile source_info = new SourceFile (file, url);
- sources.Add (url, source_info);
- return source_info;
- }
-
- public void DefineField (
- SymbolToken parent,
- string name,
- FieldAttributes attributes,
- byte[] signature,
- SymAddressKind addrKind,
- int addr1,
- int addr2,
- int addr3)
- {
- throw new NotSupportedException ();
- }
-
- public void DefineGlobalVariable (
- string name,
- FieldAttributes attributes,
- byte[] signature,
- SymAddressKind addrKind,
- int addr1,
- int addr2,
- int addr3)
- {
- throw new NotSupportedException ();
- }
+ public void CloseNamespace ()
+ { }
- public void DefineLocalVariable (string name,
- FieldAttributes attributes,
- byte[] signature,
- SymAddressKind addrKind,
- int addr1,
- int addr2,
- int addr3,
- int startOffset,
- int endOffset)
+ public void DefineLocalVariable (string name, byte[] signature)
{
if (current_method == null)
return;
- current_method.AddLocal (name, attributes, signature);
- }
-
- public void DefineParameter (string name,
- ParameterAttributes attributes,
- int sequence,
- SymAddressKind addrKind,
- int addr1,
- int addr2,
- int addr3)
- {
- throw new NotSupportedException ();
- }
-
- public void DefineSequencePoints (ISymbolDocumentWriter document,
- int[] offsets,
- int[] lines,
- int[] columns,
- int[] endLines,
- int[] endColumns)
- {
- throw new NotSupportedException ();
+ current_method.AddLocal (name, signature);
}
public void MarkSequencePoint (int offset, int line, int column)
current_method_lines [current_method_lines_pos++] = new LineNumberEntry (line, offset);
}
- public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
- {
- throw new NotSupportedException ();
- }
-
- public void OpenMethod (SymbolToken symbol_token)
- {
- throw new NotSupportedException ();
- }
-
- public void SetMethodSourceRange (ISymbolDocumentWriter startDoc,
- int startLine, int startColumn,
- ISymbolDocumentWriter endDoc,
- int endLine, int endColumn)
- {
- throw new NotSupportedException ();
- }
-
- public void OpenMethod (ISymbolDocumentWriter document, int startLine, int startColumn,
- int endLine, int endColumn, MethodBase method, int namespace_id)
+ public void OpenMethod (ISourceFile file, ISourceMethod method,
+ int startRow, int startColumn,
+ int endRow, int endColumn)
{
- SourceFile source_info = document as SourceFile;
-
- if ((source_info == null) || (method == null))
- throw new NullReferenceException ();
-
- current_method = new SourceMethod (file, source_info, startLine, startColumn,
- endLine, endColumn, method, namespace_id);
+ SourceMethod source = new SourceMethod (
+ file, method, startRow, startColumn, endRow, endColumn);
+ current_method = source;
methods.Add (current_method);
- source_info.AddMethod (current_method);
}
public void CloseMethod ()
{
- current_method.SetLineNumbers (current_method_lines, current_method_lines_pos);
+ current_method.SetLineNumbers (
+ current_method_lines, current_method_lines_pos);
current_method_lines_pos = 0;
current_method = null;
}
- public int DefineNamespace (string name, ISymbolDocumentWriter document,
- string[] using_clauses, int parent)
+ public SourceFileEntry DefineDocument (string url)
{
- if ((document == null) || (using_clauses == null))
- throw new NullReferenceException ();
- if (!(document is SourceFile))
- throw new ArgumentException ();
-
- SourceFile source_info = (SourceFile) document;
-
- return source_info.DefineNamespace (name, using_clauses, parent);
+ SourceFileEntry entry = new SourceFileEntry (file, url);
+ sources.Add (entry);
+ return entry;
}
- public void OpenNamespace (string name)
+ public int DefineNamespace (string name, SourceFileEntry source,
+ string[] using_clauses, int parent)
{
- throw new NotSupportedException ();
+ if ((source == null) || (using_clauses == null))
+ throw new NullReferenceException ();
+
+ return source.DefineNamespace (name, using_clauses, parent);
}
public int OpenScope (int startOffset)
current_method.EndBlock (endOffset);
}
- public void SetScopeRange (int scopeID, int startOffset, int endOffset)
+ protected byte[] CreateOutput (Guid guid)
{
- throw new NotSupportedException ();
- }
+ 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)
- {
- throw new NotSupportedException ();
+ return file.CreateSymbolFile (guid);
}
- public void SetUnderlyingWriter (IntPtr underlyingWriter)
+ public void WriteSymbolFile (Guid guid)
{
- throw new NotSupportedException ();
+ 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
{
- throw new NotSupportedException ();
- }
+ 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;
- public void UsingNamespace (string fullName)
- {
- throw new NotSupportedException ();
- }
+ private LexicalBlockEntry _implicit_block;
- //
- // MonoSymbolWriter implementation
- //
- protected void DoFixups (Assembly assembly)
- {
- foreach (SourceMethod method in methods) {
- if (method._method_base is MethodBuilder) {
- MethodBuilder mb = (MethodBuilder) method._method_base;
- method._token = mb.GetToken ().Token;
- } else if (method._method_base is ConstructorBuilder) {
- ConstructorBuilder cb = (ConstructorBuilder) method._method_base;
- method._token = cb.GetToken ().Token;
- } else
- throw new NotSupportedException ();
-
- if (method.SourceFile == null)
- orphant_methods.Add (method);
+ public SourceMethod (ISourceFile file, ISourceMethod method,
+ int startLine, int startColumn,
+ int endLine, int endColumn)
+ {
+ this._file = file;
+ this._method = method;
+
+ this._start = new LineNumberEntry (startLine, 0);
+ this._end = new LineNumberEntry (endLine, 0);
+
+ this._implicit_block = new LexicalBlockEntry (0, 0);
}
- }
- protected byte[] CreateOutput (Assembly assembly)
- {
- foreach (SourceMethod method in Methods) {
- if (!method.HasSource) {
- Console.WriteLine ("INGORING METHOD: {0}", method);
- continue;
+ 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);
+ }
+
+ public void EndBlock (int endOffset)
+ {
+ LexicalBlockEntry block =
+ (LexicalBlockEntry) _block_stack.Pop ();
+
+ block.Close (endOffset);
+ }
+
+ public LexicalBlockEntry[] Blocks {
+ get {
+ if (_blocks == null)
+ return new LexicalBlockEntry [0];
+ else {
+ LexicalBlockEntry[] retval =
+ new LexicalBlockEntry [_blocks.Count];
+ _blocks.CopyTo (retval, 0);
+ return retval;
+ }
+ }
+ }
+
+ public LexicalBlockEntry CurrentBlock {
+ get {
+ if ((_block_stack != null) && (_block_stack.Count > 0))
+ return (LexicalBlockEntry) _block_stack.Peek ();
+ else
+ return _implicit_block;
+ }
+ }
+
+ public LineNumberEntry[] Lines {
+ get {
+ return lines;
+ }
+ }
+
+ public LocalVariableEntry[] Locals {
+ get {
+ if (_locals == null)
+ return new LocalVariableEntry [0];
+ else {
+ LocalVariableEntry[] retval =
+ new LocalVariableEntry [_locals.Count];
+ _locals.CopyTo (retval, 0);
+ return retval;
+ }
}
+ }
- method.SourceFile.DefineMethod (
- method.MethodBase, method.Token, method.Locals,
- method.Lines, method.Blocks, method.Start.Row, method.End.Row,
- method.NamespaceID);
+ public void AddLocal (string name, byte[] signature)
+ {
+ if (_locals == null)
+ _locals = new ArrayList ();
+ _locals.Add (new LocalVariableEntry (
+ name, signature, CurrentBlock.Index));
}
- return file.CreateSymbolFile ();
+ public ISourceFile SourceFile {
+ get { return _file; }
+ }
+
+ public ISourceMethod Method {
+ get { return _method; }
+ }
+
+ 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);
+ }
}
}
}
-