2 // Mono.CSharp.Debugger/MonoSymbolWriter.cs
5 // Martin Baulig (martin@ximian.com)
7 // This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter
10 // (C) 2002 Ximian, Inc. http://www.ximian.com
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System
.Runtime
.CompilerServices
;
36 using System
.Collections
;
39 namespace Mono
.CompilerServices
.SymbolWriter
41 public class MonoSymbolWriter
43 ArrayList methods
= null;
44 ArrayList sources
= null;
45 ArrayList comp_units
= null;
46 protected readonly MonoSymbolFile file
;
47 string filename
= null;
49 private SourceMethodBuilder current_method
= null;
50 private Stack current_method_stack
;
52 public MonoSymbolWriter (string filename
)
54 this.methods
= new ArrayList ();
55 this.sources
= new ArrayList ();
56 this.comp_units
= new ArrayList ();
57 this.current_method_stack
= new Stack ();
58 this.file
= new MonoSymbolFile ();
60 this.filename
= filename
+ ".mdb";
63 public MonoSymbolFile SymbolFile
{
67 public void CloseNamespace ()
70 public void DefineLocalVariable (int index
, string name
)
72 if (current_method
== null)
75 current_method
.AddLocal (index
, name
);
78 public void DefineCapturedLocal (int scope_id
, string name
, string captured_name
)
80 file
.DefineCapturedVariable (scope_id
, name
, captured_name
,
81 CapturedVariable
.CapturedKind
.Local
);
84 public void DefineCapturedParameter (int scope_id
, string name
, string captured_name
)
86 file
.DefineCapturedVariable (scope_id
, name
, captured_name
,
87 CapturedVariable
.CapturedKind
.Parameter
);
90 public void DefineCapturedThis (int scope_id
, string captured_name
)
92 file
.DefineCapturedVariable (scope_id
, "this", captured_name
,
93 CapturedVariable
.CapturedKind
.This
);
96 public void DefineCapturedScope (int scope_id
, int id
, string captured_name
)
98 file
.DefineCapturedScope (scope_id
, id
, captured_name
);
101 public void DefineScopeVariable (int scope
, int index
)
103 if (current_method
== null)
106 current_method
.AddScopeVariable (scope
, index
);
109 public void MarkSequencePoint (int offset
, SourceFileEntry file
, int line
, int column
,
112 if (current_method
== null)
115 current_method
.MarkSequencePoint (offset
, file
, line
, column
, is_hidden
);
118 public SourceMethodBuilder
OpenMethod (ICompileUnit file
, int ns_id
, IMethodDef method
)
120 SourceMethodBuilder builder
= new SourceMethodBuilder (file
, ns_id
, method
);
121 current_method_stack
.Push (current_method
);
122 current_method
= builder
;
123 methods
.Add (current_method
);
127 public void CloseMethod ()
129 current_method
= (SourceMethodBuilder
) current_method_stack
.Pop ();
132 public SourceFileEntry
DefineDocument (string url
)
134 SourceFileEntry entry
= new SourceFileEntry (file
, url
);
139 public SourceFileEntry
DefineDocument (string url
, byte[] guid
, byte[] checksum
)
141 SourceFileEntry entry
= new SourceFileEntry (file
, url
, guid
, checksum
);
146 public CompileUnitEntry
DefineCompilationUnit (SourceFileEntry source
)
148 CompileUnitEntry entry
= new CompileUnitEntry (file
, source
);
149 comp_units
.Add (entry
);
153 public int DefineNamespace (string name
, CompileUnitEntry unit
,
154 string[] using_clauses
, int parent
)
156 if ((unit
== null) || (using_clauses
== null))
157 throw new NullReferenceException ();
159 return unit
.DefineNamespace (name
, using_clauses
, parent
);
162 public int OpenScope (int start_offset
)
164 if (current_method
== null)
167 current_method
.StartBlock (CodeBlockEntry
.Type
.Lexical
, start_offset
);
171 public void CloseScope (int end_offset
)
173 if (current_method
== null)
176 current_method
.EndBlock (end_offset
);
179 public void OpenCompilerGeneratedBlock (int start_offset
)
181 if (current_method
== null)
184 current_method
.StartBlock (CodeBlockEntry
.Type
.CompilerGenerated
,
188 public void CloseCompilerGeneratedBlock (int end_offset
)
190 if (current_method
== null)
193 current_method
.EndBlock (end_offset
);
196 public void StartIteratorBody (int start_offset
)
198 current_method
.StartBlock (CodeBlockEntry
.Type
.IteratorBody
,
202 public void EndIteratorBody (int end_offset
)
204 current_method
.EndBlock (end_offset
);
207 public void StartIteratorDispatcher (int start_offset
)
209 current_method
.StartBlock (CodeBlockEntry
.Type
.IteratorDispatcher
,
213 public void EndIteratorDispatcher (int end_offset
)
215 current_method
.EndBlock (end_offset
);
218 public void DefineAnonymousScope (int id
)
220 file
.DefineAnonymousScope (id
);
223 public void WriteSymbolFile (Guid guid
)
225 foreach (SourceMethodBuilder method
in methods
)
226 method
.DefineMethod (file
);
229 // We mmap the file, so unlink the previous version since it may be in use
230 File
.Delete (filename
);
232 // We can safely ignore
234 using (FileStream fs
= new FileStream (filename
, FileMode
.Create
, FileAccess
.Write
)) {
235 file
.CreateSymbolFile (guid
, fs
);
240 public class SourceMethodBuilder
244 ArrayList _scope_vars
;
248 ICompileUnit _comp_unit
;
249 // MethodEntry.Flags _method_flags;
252 public SourceMethodBuilder (ICompileUnit comp_unit
, int ns_id
, IMethodDef method
)
254 this._comp_unit
= comp_unit
;
255 this._method
= method
;
258 method_lines
= new LineNumberEntry
[32];
261 private LineNumberEntry
[] method_lines
;
262 private int method_lines_pos
= 0;
264 public void MarkSequencePoint (int offset
, SourceFileEntry file
, int line
, int column
,
267 if (method_lines_pos
== method_lines
.Length
) {
268 LineNumberEntry
[] tmp
= method_lines
;
269 method_lines
= new LineNumberEntry
[method_lines
.Length
* 2];
270 Array
.Copy (tmp
, method_lines
, method_lines_pos
);
273 int file_idx
= file
!= null ? file
.Index
: 0;
274 method_lines
[method_lines_pos
++] = new LineNumberEntry (
275 file_idx
, line
, offset
, is_hidden
);
278 public void StartBlock (CodeBlockEntry
.Type type
, int start_offset
)
280 if (_block_stack
== null)
281 _block_stack
= new Stack ();
283 _blocks
= new ArrayList ();
285 int parent
= CurrentBlock
!= null ? CurrentBlock
.Index
: -1;
287 CodeBlockEntry block
= new CodeBlockEntry (
288 _blocks
.Count
+ 1, parent
, type
, start_offset
);
290 _block_stack
.Push (block
);
294 public void EndBlock (int end_offset
)
296 CodeBlockEntry block
= (CodeBlockEntry
) _block_stack
.Pop ();
297 block
.Close (end_offset
);
300 public CodeBlockEntry
[] Blocks
{
303 return new CodeBlockEntry
[0];
305 CodeBlockEntry
[] retval
= new CodeBlockEntry
[_blocks
.Count
];
306 _blocks
.CopyTo (retval
, 0);
311 public CodeBlockEntry CurrentBlock
{
313 if ((_block_stack
!= null) && (_block_stack
.Count
> 0))
314 return (CodeBlockEntry
) _block_stack
.Peek ();
320 public LocalVariableEntry
[] Locals
{
323 return new LocalVariableEntry
[0];
325 LocalVariableEntry
[] retval
=
326 new LocalVariableEntry
[_locals
.Count
];
327 _locals
.CopyTo (retval
, 0);
333 public void AddLocal (int index
, string name
)
336 _locals
= new ArrayList ();
337 int block_idx
= CurrentBlock
!= null ? CurrentBlock
.Index
: 0;
338 _locals
.Add (new LocalVariableEntry (index
, name
, block_idx
));
341 public ScopeVariable
[] ScopeVariables
{
343 if (_scope_vars
== null)
344 return new ScopeVariable
[0];
346 ScopeVariable
[] retval
= new ScopeVariable
[_scope_vars
.Count
];
347 _scope_vars
.CopyTo (retval
);
352 public void AddScopeVariable (int scope
, int index
)
354 if (_scope_vars
== null)
355 _scope_vars
= new ArrayList ();
357 new ScopeVariable (scope
, index
));
360 public string RealMethodName
{
361 get { return _real_name; }
364 public void SetRealMethodName (string name
)
369 public ICompileUnit SourceFile
{
370 get { return _comp_unit; }
373 public IMethodDef Method
{
374 get { return _method; }
377 public void DefineMethod (MonoSymbolFile file
)
379 LineNumberEntry
[] lines
= new LineNumberEntry
[method_lines_pos
];
380 Array
.Copy (method_lines
, lines
, method_lines_pos
);
382 MethodEntry entry
= new MethodEntry (
383 file
, _comp_unit
.Entry
, _method
.Token
, ScopeVariables
,
384 Locals
, lines
, Blocks
, RealMethodName
, 0, //_method_flags,
387 file
.AddMethod (entry
);