[mcs] Add pathmap option
[mono.git] / mcs / class / Mono.CompilerServices.SymbolWriter / MonoSymbolTable.cs
1 //
2 // Mono.CSharp.Debugger/MonoSymbolTable.cs
3 //
4 // Author:
5 //   Martin Baulig (martin@ximian.com)
6 //
7 // (C) 2002 Ximian, Inc.  http://www.ximian.com
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Security.Cryptography;
33 using System.Collections.Generic;
34 using System.Text;
35 using System.IO;
36
37 //
38 // Parts which are actually written into the symbol file are marked with
39 //
40 //         #region This is actually written to the symbol file
41 //         #endregion
42 //
43 // Please do not modify these regions without previously talking to me.
44 //
45 // All changes to the file format must be synchronized in several places:
46 //
47 // a) The fields in these regions (and their order) must match the actual
48 //    contents of the symbol file.
49 //
50 //    This helps people to understand the symbol file format without reading
51 //    too much source code, ie. you look at the appropriate region and then
52 //    you know what's actually in the file.
53 //
54 //    It is also required to help me enforce b).
55 //
56 // b) The regions must be kept in sync with the unmanaged code in
57 //    mono/metadata/debug-mono-symfile.h
58 //
59 // When making changes to the file format, you must also increase two version
60 // numbers:
61 //
62 // i)  OffsetTable.Version in this file.
63 // ii) MONO_SYMBOL_FILE_VERSION in mono/metadata/debug-mono-symfile.h
64 //
65 // After doing so, recompile everything, including the debugger.  Symbol files
66 // with different versions are incompatible to each other and the debugger and
67 // the runtime enfore this, so you need to recompile all your assemblies after
68 // changing the file format.
69 //
70
71 namespace Mono.CompilerServices.SymbolWriter
72 {
73         public class OffsetTable
74         {
75                 public const int  MajorVersion = 50;
76                 public const int  MinorVersion = 0;
77                 public const long Magic        = 0x45e82623fd7fa614;
78
79                 #region This is actually written to the symbol file
80                 public int TotalFileSize;
81                 public int DataSectionOffset;
82                 public int DataSectionSize;
83                 public int CompileUnitCount;
84                 public int CompileUnitTableOffset;
85                 public int CompileUnitTableSize;
86                 public int SourceCount;
87                 public int SourceTableOffset;
88                 public int SourceTableSize;
89                 public int MethodCount;
90                 public int MethodTableOffset;
91                 public int MethodTableSize;
92                 public int TypeCount;
93                 public int AnonymousScopeCount;
94                 public int AnonymousScopeTableOffset;
95                 public int AnonymousScopeTableSize;
96
97                 [Flags]
98                 public enum Flags
99                 {
100                         IsAspxSource            = 1,
101                         WindowsFileNames        = 2
102                 }
103
104                 public Flags FileFlags;
105
106                 public int LineNumberTable_LineBase = LineNumberTable.Default_LineBase;
107                 public int LineNumberTable_LineRange = LineNumberTable.Default_LineRange;
108                 public int LineNumberTable_OpcodeBase = LineNumberTable.Default_OpcodeBase;
109                 #endregion
110
111                 internal OffsetTable ()
112                 {
113                         int platform = (int) Environment.OSVersion.Platform;
114                         if ((platform != 4) && (platform != 128))
115                                 FileFlags |= Flags.WindowsFileNames;
116                 }
117
118                 internal OffsetTable (BinaryReader reader, int major_version, int minor_version)
119                 {
120                         TotalFileSize = reader.ReadInt32 ();
121                         DataSectionOffset = reader.ReadInt32 ();
122                         DataSectionSize = reader.ReadInt32 ();
123                         CompileUnitCount = reader.ReadInt32 ();
124                         CompileUnitTableOffset = reader.ReadInt32 ();
125                         CompileUnitTableSize = reader.ReadInt32 ();
126                         SourceCount = reader.ReadInt32 ();
127                         SourceTableOffset = reader.ReadInt32 ();
128                         SourceTableSize = reader.ReadInt32 ();
129                         MethodCount = reader.ReadInt32 ();
130                         MethodTableOffset = reader.ReadInt32 ();
131                         MethodTableSize = reader.ReadInt32 ();
132                         TypeCount = reader.ReadInt32 ();
133
134                         AnonymousScopeCount = reader.ReadInt32 ();
135                         AnonymousScopeTableOffset = reader.ReadInt32 ();
136                         AnonymousScopeTableSize = reader.ReadInt32 ();
137
138                         LineNumberTable_LineBase = reader.ReadInt32 ();
139                         LineNumberTable_LineRange = reader.ReadInt32 ();
140                         LineNumberTable_OpcodeBase = reader.ReadInt32 ();
141
142                         FileFlags = (Flags) reader.ReadInt32 ();
143                 }
144
145                 internal void Write (BinaryWriter bw, int major_version, int minor_version)
146                 {
147                         bw.Write (TotalFileSize);
148                         bw.Write (DataSectionOffset);
149                         bw.Write (DataSectionSize);
150                         bw.Write (CompileUnitCount);
151                         bw.Write (CompileUnitTableOffset);
152                         bw.Write (CompileUnitTableSize);
153                         bw.Write (SourceCount);
154                         bw.Write (SourceTableOffset);
155                         bw.Write (SourceTableSize);
156                         bw.Write (MethodCount);
157                         bw.Write (MethodTableOffset);
158                         bw.Write (MethodTableSize);
159                         bw.Write (TypeCount);
160
161                         bw.Write (AnonymousScopeCount);
162                         bw.Write (AnonymousScopeTableOffset);
163                         bw.Write (AnonymousScopeTableSize);
164
165                         bw.Write (LineNumberTable_LineBase);
166                         bw.Write (LineNumberTable_LineRange);
167                         bw.Write (LineNumberTable_OpcodeBase);
168
169                         bw.Write ((int) FileFlags);
170                 }
171
172                 public override string ToString ()
173                 {
174                         return String.Format (
175                                 "OffsetTable [{0} - {1}:{2} - {3}:{4}:{5} - {6}:{7}:{8} - {9}]",
176                                 TotalFileSize, DataSectionOffset, DataSectionSize, SourceCount,
177                                 SourceTableOffset, SourceTableSize, MethodCount, MethodTableOffset,
178                                 MethodTableSize, TypeCount);
179                 }
180         }
181
182         public class LineNumberEntry
183         {
184                 #region This is actually written to the symbol file
185                 public readonly int Row;
186                 public int Column;
187                 public int EndRow, EndColumn;
188                 public readonly int File;
189                 public readonly int Offset;
190                 public readonly bool IsHidden;  // Obsolete is never used
191                 #endregion
192
193                 public sealed class LocationComparer : IComparer<LineNumberEntry>
194                 {
195                         public static readonly LocationComparer Default = new LocationComparer ();
196
197                         public int Compare (LineNumberEntry l1, LineNumberEntry l2)
198                         {
199                                 return l1.Row == l2.Row ?
200                                         l1.Column.CompareTo (l2.Column) :
201                                         l1.Row.CompareTo (l2.Row);
202                         }
203                 }
204
205                 public static readonly LineNumberEntry Null = new LineNumberEntry (0, 0, 0, 0);
206
207                 public LineNumberEntry (int file, int row, int column, int offset)
208                         : this (file, row, column, offset, false)
209                 {
210                 }
211
212                 public LineNumberEntry (int file, int row, int offset)
213                         : this (file, row, -1, offset, false)
214                 {
215                 }
216
217                 public LineNumberEntry (int file, int row, int column, int offset, bool is_hidden)
218                 : this (file, row, column, -1, -1, offset, is_hidden)
219                 {
220                 }
221
222                 public LineNumberEntry (int file, int row, int column, int end_row, int end_column, int offset, bool is_hidden)
223                 {
224                         this.File = file;
225                         this.Row = row;
226                         this.Column = column;
227                         this.EndRow = end_row;
228                         this.EndColumn = end_column;
229                         this.Offset = offset;
230                         this.IsHidden = is_hidden;
231                 }
232
233                 public override string ToString ()
234                 {
235                         return String.Format ("[Line {0}:{1,2}-{3,4}:{5}]", File, Row, Column, EndRow, EndColumn, Offset);
236                 }
237         }
238
239         public class CodeBlockEntry
240         {
241                 public int Index;
242                 #region This is actually written to the symbol file
243                 public int Parent;
244                 public Type BlockType;
245                 public int StartOffset;
246                 public int EndOffset;
247                 #endregion
248
249                 public enum Type {
250                         Lexical                 = 1,
251                         CompilerGenerated       = 2,
252                         IteratorBody            = 3,
253                         IteratorDispatcher      = 4
254                 }
255
256                 public CodeBlockEntry (int index, int parent, Type type, int start_offset)
257                 {
258                         this.Index = index;
259                         this.Parent = parent;
260                         this.BlockType = type;
261                         this.StartOffset = start_offset;
262                 }
263
264                 internal CodeBlockEntry (int index, MyBinaryReader reader)
265                 {
266                         this.Index = index;
267                         int type_flag = reader.ReadLeb128 ();
268                         BlockType = (Type) (type_flag & 0x3f);
269                         this.Parent = reader.ReadLeb128 ();
270                         this.StartOffset = reader.ReadLeb128 ();
271                         this.EndOffset = reader.ReadLeb128 ();
272
273                         /* Reserved for future extensions. */
274                         if ((type_flag & 0x40) != 0) {
275                                 int data_size = reader.ReadInt16 ();
276                                 reader.BaseStream.Position += data_size;
277                         }                               
278                 }
279
280                 public void Close (int end_offset)
281                 {
282                         this.EndOffset = end_offset;
283                 }
284
285                 internal void Write (MyBinaryWriter bw)
286                 {
287                         bw.WriteLeb128 ((int) BlockType);
288                         bw.WriteLeb128 (Parent);
289                         bw.WriteLeb128 (StartOffset);
290                         bw.WriteLeb128 (EndOffset);
291                 }
292
293                 public override string ToString ()
294                 {
295                         return String.Format ("[CodeBlock {0}:{1}:{2}:{3}:{4}]",
296                                               Index, Parent, BlockType, StartOffset, EndOffset);
297                 }
298         }
299
300         public struct LocalVariableEntry
301         {
302                 #region This is actually written to the symbol file
303                 public readonly int Index;
304                 public readonly string Name;
305                 public readonly int BlockIndex;
306                 #endregion
307
308                 public LocalVariableEntry (int index, string name, int block)
309                 {
310                         this.Index = index;
311                         this.Name = name;
312                         this.BlockIndex = block;
313                 }
314
315                 internal LocalVariableEntry (MonoSymbolFile file, MyBinaryReader reader)
316                 {
317                         Index = reader.ReadLeb128 ();
318                         Name = reader.ReadString ();
319                         BlockIndex = reader.ReadLeb128 ();
320                 }
321
322                 internal void Write (MonoSymbolFile file, MyBinaryWriter bw)
323                 {
324                         bw.WriteLeb128 (Index);
325                         bw.Write (Name);
326                         bw.WriteLeb128 (BlockIndex);
327                 }
328
329                 public override string ToString ()
330                 {
331                         return String.Format ("[LocalVariable {0}:{1}:{2}]",
332                                               Name, Index, BlockIndex - 1);
333                 }
334         }
335
336         public struct CapturedVariable
337         {
338                 #region This is actually written to the symbol file
339                 public readonly string Name;
340                 public readonly string CapturedName;
341                 public readonly CapturedKind Kind;
342                 #endregion
343
344                 public enum CapturedKind : byte
345                 {
346                         Local,
347                         Parameter,
348                         This
349                 }
350
351                 public CapturedVariable (string name, string captured_name,
352                                          CapturedKind kind)
353                 {
354                         this.Name = name;
355                         this.CapturedName = captured_name;
356                         this.Kind = kind;
357                 }
358
359                 internal CapturedVariable (MyBinaryReader reader)
360                 {
361                         Name = reader.ReadString ();
362                         CapturedName = reader.ReadString ();
363                         Kind = (CapturedKind) reader.ReadByte ();
364                 }
365
366                 internal void Write (MyBinaryWriter bw)
367                 {
368                         bw.Write (Name);
369                         bw.Write (CapturedName);
370                         bw.Write ((byte) Kind);
371                 }
372
373                 public override string ToString ()
374                 {
375                         return String.Format ("[CapturedVariable {0}:{1}:{2}]",
376                                               Name, CapturedName, Kind);
377                 }
378         }
379
380         public struct CapturedScope
381         {
382                 #region This is actually written to the symbol file
383                 public readonly int Scope;
384                 public readonly string CapturedName;
385                 #endregion
386
387                 public CapturedScope (int scope, string captured_name)
388                 {
389                         this.Scope = scope;
390                         this.CapturedName = captured_name;
391                 }
392
393                 internal CapturedScope (MyBinaryReader reader)
394                 {
395                         Scope = reader.ReadLeb128 ();
396                         CapturedName = reader.ReadString ();
397                 }
398
399                 internal void Write (MyBinaryWriter bw)
400                 {
401                         bw.WriteLeb128 (Scope);
402                         bw.Write (CapturedName);
403                 }
404
405                 public override string ToString ()
406                 {
407                         return String.Format ("[CapturedScope {0}:{1}]",
408                                               Scope, CapturedName);
409                 }
410         }
411
412         public struct ScopeVariable
413         {
414                 #region This is actually written to the symbol file
415                 public readonly int Scope;
416                 public readonly int Index;
417                 #endregion
418
419                 public ScopeVariable (int scope, int index)
420                 {
421                         this.Scope = scope;
422                         this.Index = index;
423                 }
424
425                 internal ScopeVariable (MyBinaryReader reader)
426                 {
427                         Scope = reader.ReadLeb128 ();
428                         Index = reader.ReadLeb128 ();
429                 }
430
431                 internal void Write (MyBinaryWriter bw)
432                 {
433                         bw.WriteLeb128 (Scope);
434                         bw.WriteLeb128 (Index);
435                 }
436
437                 public override string ToString ()
438                 {
439                         return String.Format ("[ScopeVariable {0}:{1}]", Scope, Index);
440                 }
441         }
442
443         public class AnonymousScopeEntry
444         {
445                 #region This is actually written to the symbol file
446                 public readonly int ID;
447                 #endregion
448
449                 List<CapturedVariable> captured_vars = new List<CapturedVariable> ();
450                 List<CapturedScope> captured_scopes = new List<CapturedScope> ();
451
452                 public AnonymousScopeEntry (int id)
453                 {
454                         this.ID = id;
455                 }
456
457                 internal AnonymousScopeEntry (MyBinaryReader reader)
458                 {
459                         ID = reader.ReadLeb128 ();
460
461                         int num_captured_vars = reader.ReadLeb128 ();
462                         for (int i = 0; i < num_captured_vars; i++)
463                                 captured_vars.Add (new CapturedVariable (reader));
464
465                         int num_captured_scopes = reader.ReadLeb128 ();
466                         for (int i = 0; i < num_captured_scopes; i++)
467                                 captured_scopes.Add (new CapturedScope (reader));
468                 }
469
470                 internal void AddCapturedVariable (string name, string captured_name,
471                                                    CapturedVariable.CapturedKind kind)
472                 {
473                         captured_vars.Add (new CapturedVariable (name, captured_name, kind));
474                 }
475
476                 public CapturedVariable[] CapturedVariables {
477                         get {
478                                 CapturedVariable[] retval = new CapturedVariable [captured_vars.Count];
479                                 captured_vars.CopyTo (retval, 0);
480                                 return retval;
481                         }
482                 }
483
484                 internal void AddCapturedScope (int scope, string captured_name)
485                 {
486                         captured_scopes.Add (new CapturedScope (scope, captured_name));
487                 }
488
489                 public CapturedScope[] CapturedScopes {
490                         get {
491                                 CapturedScope[] retval = new CapturedScope [captured_scopes.Count];
492                                 captured_scopes.CopyTo (retval, 0);
493                                 return retval;
494                         }
495                 }
496
497                 internal void Write (MyBinaryWriter bw)
498                 {
499                         bw.WriteLeb128 (ID);
500
501                         bw.WriteLeb128 (captured_vars.Count);
502                         foreach (CapturedVariable cv in captured_vars)
503                                 cv.Write (bw);
504
505                         bw.WriteLeb128 (captured_scopes.Count);
506                         foreach (CapturedScope cs in captured_scopes)
507                                 cs.Write (bw);
508                 }
509
510                 public override string ToString ()
511                 {
512                         return String.Format ("[AnonymousScope {0}]", ID);
513                 }
514         }
515
516         public class CompileUnitEntry : ICompileUnit
517         {
518                 #region This is actually written to the symbol file
519                 public readonly int Index;
520                 int DataOffset;
521                 #endregion
522
523                 MonoSymbolFile file;
524                 SourceFileEntry source;
525                 List<SourceFileEntry> include_files;
526                 List<NamespaceEntry> namespaces;
527
528                 bool creating;
529
530                 public static int Size {
531                         get { return 8; }
532                 }
533
534                 CompileUnitEntry ICompileUnit.Entry {
535                         get { return this; }
536                 }
537
538                 public CompileUnitEntry (MonoSymbolFile file, SourceFileEntry source)
539                 {
540                         this.file = file;
541                         this.source = source;
542
543                         this.Index = file.AddCompileUnit (this);
544
545                         creating = true;
546                         namespaces = new List<NamespaceEntry> ();
547                 }
548
549                 public void AddFile (SourceFileEntry file)
550                 {
551                         if (!creating)
552                                 throw new InvalidOperationException ();
553
554                         if (include_files == null)
555                                 include_files = new List<SourceFileEntry> ();
556
557                         include_files.Add (file);
558                 }
559
560                 public SourceFileEntry SourceFile {
561                         get {
562                                 if (creating)
563                                         return source;
564
565                                 ReadData ();
566                                 return source;
567                         }
568                 }
569
570                 public int DefineNamespace (string name, string[] using_clauses, int parent)
571                 {
572                         if (!creating)
573                                 throw new InvalidOperationException ();
574
575                         int index = file.GetNextNamespaceIndex ();
576                         NamespaceEntry ns = new NamespaceEntry (name, index, using_clauses, parent);
577                         namespaces.Add (ns);
578                         return index;
579                 }
580
581                 internal void WriteData (MyBinaryWriter bw)
582                 {
583                         DataOffset = (int) bw.BaseStream.Position;
584                         bw.WriteLeb128 (source.Index);
585
586                         int count_includes = include_files != null ? include_files.Count : 0;
587                         bw.WriteLeb128 (count_includes);
588                         if (include_files != null) {
589                                 foreach (SourceFileEntry entry in include_files)
590                                         bw.WriteLeb128 (entry.Index);
591                         }
592
593                         bw.WriteLeb128 (namespaces.Count);
594                         foreach (NamespaceEntry ns in namespaces)
595                                 ns.Write (file, bw);
596                 }
597
598                 internal void Write (BinaryWriter bw)
599                 {
600                         bw.Write (Index);
601                         bw.Write (DataOffset);
602                 }
603
604                 internal CompileUnitEntry (MonoSymbolFile file, MyBinaryReader reader)
605                 {
606                         this.file = file;
607
608                         Index = reader.ReadInt32 ();
609                         DataOffset = reader.ReadInt32 ();
610                 }
611
612                 public void ReadAll ()
613                 {
614                         ReadData ();
615                 }
616
617                 void ReadData ()
618                 {
619                         if (creating)
620                                 throw new InvalidOperationException ();
621
622                         lock (file) {
623                                 if (namespaces != null)
624                                         return;
625
626                                 MyBinaryReader reader = file.BinaryReader;
627                                 int old_pos = (int) reader.BaseStream.Position;
628
629                                 reader.BaseStream.Position = DataOffset;
630
631                                 int source_idx = reader.ReadLeb128 ();
632                                 source = file.GetSourceFile (source_idx);
633
634                                 int count_includes = reader.ReadLeb128 ();
635                                 if (count_includes > 0) {
636                                         include_files = new List<SourceFileEntry> ();
637                                         for (int i = 0; i < count_includes; i++)
638                                                 include_files.Add (file.GetSourceFile (reader.ReadLeb128 ()));
639                                 }
640
641                                 int count_ns = reader.ReadLeb128 ();
642                                 namespaces = new List<NamespaceEntry> ();
643                                 for (int i = 0; i < count_ns; i ++)
644                                         namespaces.Add (new NamespaceEntry (file, reader));
645
646                                 reader.BaseStream.Position = old_pos;
647                         }
648                 }
649
650                 public NamespaceEntry[] Namespaces {
651                         get {
652                                 ReadData ();
653                                 NamespaceEntry[] retval = new NamespaceEntry [namespaces.Count];
654                                 namespaces.CopyTo (retval, 0);
655                                 return retval;
656                         }
657                 }
658
659                 public SourceFileEntry[] IncludeFiles {
660                         get {
661                                 ReadData ();
662                                 if (include_files == null)
663                                         return new SourceFileEntry [0];
664
665                                 SourceFileEntry[] retval = new SourceFileEntry [include_files.Count];
666                                 include_files.CopyTo (retval, 0);
667                                 return retval;
668                         }
669                 }
670         }
671
672         public class SourceFileEntry
673         {
674                 #region This is actually written to the symbol file
675                 public readonly int Index;
676                 int DataOffset;
677                 #endregion
678
679                 MonoSymbolFile file;
680                 string file_name;
681                 byte[] guid;
682                 byte[] hash;
683                 bool creating;
684                 bool auto_generated;
685                 readonly string sourceFile;
686
687                 public static int Size {
688                         get { return 8; }
689                 }
690
691                 public SourceFileEntry (MonoSymbolFile file, string file_name)
692                 {
693                         this.file = file;
694                         this.file_name = file_name;
695                         this.Index = file.AddSource (this);
696
697                         creating = true;
698                 }
699
700                 public SourceFileEntry (MonoSymbolFile file, string sourceFile, byte [] guid, byte [] checksum)
701                         : this (file, sourceFile, sourceFile, guid, checksum)
702                 {
703                 }
704
705                 public SourceFileEntry (MonoSymbolFile file, string fileName, string sourceFile, byte[] guid, byte[] checksum)
706                         : this (file, fileName)
707                 {
708                         this.guid = guid;
709                         this.hash = checksum;
710                         this.sourceFile = sourceFile;
711                 }
712
713                 public byte[] Checksum {
714                         get {
715                                 return hash;
716                         }
717                 }
718
719                 internal void WriteData (MyBinaryWriter bw)
720                 {
721                         DataOffset = (int) bw.BaseStream.Position;
722                         bw.Write (file_name);
723
724                         if (guid == null)
725                                 guid = new byte[16];
726
727                         if (hash == null) {
728                                 try {
729                                     using (FileStream fs = new FileStream (sourceFile, FileMode.Open, FileAccess.Read)) {
730                                         MD5 md5 = MD5.Create ();
731                                         hash = md5.ComputeHash (fs);
732                                     }
733                                 } catch {
734                                         hash = new byte [16];
735                                 }
736                         }
737
738                         bw.Write (guid);
739                         bw.Write (hash);
740                         bw.Write ((byte) (auto_generated ? 1 : 0));
741                 }
742
743                 internal void Write (BinaryWriter bw)
744                 {
745                         bw.Write (Index);
746                         bw.Write (DataOffset);
747                 }
748
749                 internal SourceFileEntry (MonoSymbolFile file, MyBinaryReader reader)
750                 {
751                         this.file = file;
752
753                         Index = reader.ReadInt32 ();
754                         DataOffset = reader.ReadInt32 ();
755
756                         int old_pos = (int) reader.BaseStream.Position;
757                         reader.BaseStream.Position = DataOffset;
758
759                         sourceFile = file_name = reader.ReadString ();
760                         guid = reader.ReadBytes (16);
761                         hash = reader.ReadBytes (16);
762                         auto_generated = reader.ReadByte () == 1;
763
764                         reader.BaseStream.Position = old_pos;
765                 }
766
767                 public string FileName {
768                         get { return file_name; }
769                         set { file_name = value; }
770                 }
771
772                 public bool AutoGenerated {
773                         get { return auto_generated; }
774                 }
775
776                 public void SetAutoGenerated ()
777                 {
778                         if (!creating)
779                                 throw new InvalidOperationException ();
780
781                         auto_generated = true;
782                         file.OffsetTable.FileFlags |= OffsetTable.Flags.IsAspxSource;
783                 }
784
785                 public bool CheckChecksum ()
786                 {
787                         try {
788                                 using (FileStream fs = new FileStream (sourceFile, FileMode.Open)) {
789                                         MD5 md5 = MD5.Create ();
790                                         byte[] data = md5.ComputeHash (fs);
791                                         for (int i = 0; i < 16; i++)
792                                                 if (data [i] != hash [i])
793                                                         return false;
794                                         return true;
795                                 }
796                         } catch {
797                                 return false;
798                         }
799                 }
800
801                 public override string ToString ()
802                 {
803                         return String.Format ("SourceFileEntry ({0}:{1})", Index, DataOffset);
804                 }
805         }
806
807         public class LineNumberTable
808         {
809                 protected LineNumberEntry[] _line_numbers;
810                 public LineNumberEntry[] LineNumbers {
811                         get { return _line_numbers; }
812                 }
813
814                 public readonly int LineBase;
815                 public readonly int LineRange;
816                 public readonly byte OpcodeBase;
817                 public readonly int MaxAddressIncrement;
818
819 #region Configurable constants
820                 public const int Default_LineBase = -1;
821                 public const int Default_LineRange = 8;
822                 public const byte Default_OpcodeBase = 9;
823
824 #endregion
825
826                 public const byte DW_LNS_copy = 1;
827                 public const byte DW_LNS_advance_pc = 2;
828                 public const byte DW_LNS_advance_line = 3;
829                 public const byte DW_LNS_set_file = 4;
830                 public const byte DW_LNS_const_add_pc = 8;
831
832                 public const byte DW_LNE_end_sequence = 1;
833
834                 // MONO extensions.
835                 public const byte DW_LNE_MONO_negate_is_hidden = 0x40;
836
837                 internal const byte DW_LNE_MONO__extensions_start = 0x40;
838                 internal const byte DW_LNE_MONO__extensions_end   = 0x7f;
839
840                 protected LineNumberTable (MonoSymbolFile file)
841                 {
842                         this.LineBase = file.OffsetTable.LineNumberTable_LineBase;
843                         this.LineRange = file.OffsetTable.LineNumberTable_LineRange;
844                         this.OpcodeBase = (byte) file.OffsetTable.LineNumberTable_OpcodeBase;
845                         this.MaxAddressIncrement = (255 - OpcodeBase) / LineRange;
846                 }
847
848                 internal LineNumberTable (MonoSymbolFile file, LineNumberEntry[] lines)
849                         : this (file)
850                 {
851                         this._line_numbers = lines;
852                 }
853
854                 internal void Write (MonoSymbolFile file, MyBinaryWriter bw, bool hasColumnsInfo, bool hasEndInfo)
855                 {
856                         int start = (int) bw.BaseStream.Position;
857
858                         bool last_is_hidden = false;
859                         int last_line = 1, last_offset = 0, last_file = 1;
860                         for (int i = 0; i < LineNumbers.Length; i++) {
861                                 int line_inc = LineNumbers [i].Row - last_line;
862                                 int offset_inc = LineNumbers [i].Offset - last_offset;
863
864                                 if (LineNumbers [i].File != last_file) {
865                                         bw.Write (DW_LNS_set_file);
866                                         bw.WriteLeb128 (LineNumbers [i].File);
867                                         last_file = LineNumbers [i].File;
868                                 }
869
870                                 if (LineNumbers [i].IsHidden != last_is_hidden) {
871                                         bw.Write ((byte) 0);
872                                         bw.Write ((byte) 1);
873                                         bw.Write (DW_LNE_MONO_negate_is_hidden);
874                                         last_is_hidden = LineNumbers [i].IsHidden;
875                                 }
876
877                                 if (offset_inc >= MaxAddressIncrement) {
878                                         if (offset_inc < 2 * MaxAddressIncrement) {
879                                                 bw.Write (DW_LNS_const_add_pc);
880                                                 offset_inc -= MaxAddressIncrement;
881                                         } else {
882                                                 bw.Write (DW_LNS_advance_pc);
883                                                 bw.WriteLeb128 (offset_inc);
884                                                 offset_inc = 0;
885                                         }
886                                 }
887
888                                 if ((line_inc < LineBase) || (line_inc >= LineBase + LineRange)) {
889                                         bw.Write (DW_LNS_advance_line);
890                                         bw.WriteLeb128 (line_inc);
891                                         if (offset_inc != 0) {
892                                                 bw.Write (DW_LNS_advance_pc);
893                                                 bw.WriteLeb128 (offset_inc);
894                                         }
895                                         bw.Write (DW_LNS_copy);
896                                 } else {
897                                         byte opcode;
898                                         opcode = (byte) (line_inc - LineBase + (LineRange * offset_inc) +
899                                                          OpcodeBase);
900                                         bw.Write (opcode);
901                                 }
902
903                                 last_line = LineNumbers [i].Row;
904                                 last_offset = LineNumbers [i].Offset;
905                         }
906
907                         bw.Write ((byte) 0);
908                         bw.Write ((byte) 1);
909                         bw.Write (DW_LNE_end_sequence);
910
911                         if (hasColumnsInfo) {
912                                 for (int i = 0; i < LineNumbers.Length; i++) {
913                                         var ln = LineNumbers [i];
914                                         if (ln.Row >= 0)
915                                                 bw.WriteLeb128 (ln.Column);
916                                 }
917                         }
918
919                         if (hasEndInfo) {
920                                 for (int i = 0; i < LineNumbers.Length; i++) {
921                                         var ln = LineNumbers [i];
922                                         if (ln.EndRow == -1 || ln.EndColumn == -1 || ln.Row > ln.EndRow) {
923                                                 bw.WriteLeb128 (0xffffff);
924                                         } else {
925                                                 bw.WriteLeb128 (ln.EndRow - ln.Row);
926                                                 bw.WriteLeb128 (ln.EndColumn);
927                                         }
928                                 }
929                         }
930
931                         file.ExtendedLineNumberSize += (int) bw.BaseStream.Position - start;
932                 }
933
934                 internal static LineNumberTable Read (MonoSymbolFile file, MyBinaryReader br, bool readColumnsInfo, bool readEndInfo)
935                 {
936                         LineNumberTable lnt = new LineNumberTable (file);
937                         lnt.DoRead (file, br, readColumnsInfo, readEndInfo);
938                         return lnt;
939                 }
940
941                 void DoRead (MonoSymbolFile file, MyBinaryReader br, bool includesColumns, bool includesEnds)
942                 {
943                         var lines = new List<LineNumberEntry> ();
944
945                         bool is_hidden = false, modified = false;
946                         int stm_line = 1, stm_offset = 0, stm_file = 1;
947                         while (true) {
948                                 byte opcode = br.ReadByte ();
949
950                                 if (opcode == 0) {
951                                         byte size = br.ReadByte ();
952                                         long end_pos = br.BaseStream.Position + size;
953                                         opcode = br.ReadByte ();
954
955                                         if (opcode == DW_LNE_end_sequence) {
956                                                 if (modified)
957                                                         lines.Add (new LineNumberEntry (
958                                                                 stm_file, stm_line, -1, stm_offset, is_hidden));
959                                                 break;
960                                         } else if (opcode == DW_LNE_MONO_negate_is_hidden) {
961                                                 is_hidden = !is_hidden;
962                                                 modified = true;
963                                         } else if ((opcode >= DW_LNE_MONO__extensions_start) &&
964                                                    (opcode <= DW_LNE_MONO__extensions_end)) {
965                                                 ; // reserved for future extensions
966                                         } else {
967                                                 throw new MonoSymbolFileException ("Unknown extended opcode {0:x}", opcode);
968                                         }
969
970                                         br.BaseStream.Position = end_pos;
971                                         continue;
972                                 } else if (opcode < OpcodeBase) {
973                                         switch (opcode) {
974                                         case DW_LNS_copy:
975                                                 lines.Add (new LineNumberEntry (
976                                                         stm_file, stm_line, -1, stm_offset, is_hidden));
977                                                 modified = false;
978                                                 break;
979                                         case DW_LNS_advance_pc:
980                                                 stm_offset += br.ReadLeb128 ();
981                                                 modified = true;
982                                                 break;
983                                         case DW_LNS_advance_line:
984                                                 stm_line += br.ReadLeb128 ();
985                                                 modified = true;
986                                                 break;
987                                         case DW_LNS_set_file:
988                                                 stm_file = br.ReadLeb128 ();
989                                                 modified = true;
990                                                 break;
991                                         case DW_LNS_const_add_pc:
992                                                 stm_offset += MaxAddressIncrement;
993                                                 modified = true;
994                                                 break;
995                                         default:
996                                                 throw new MonoSymbolFileException (
997                                                         "Unknown standard opcode {0:x} in LNT",
998                                                         opcode);
999                                         }
1000                                 } else {
1001                                         opcode -= OpcodeBase;
1002
1003                                         stm_offset += opcode / LineRange;
1004                                         stm_line += LineBase + (opcode % LineRange);
1005                                         lines.Add (new LineNumberEntry (
1006                                                 stm_file, stm_line, -1, stm_offset, is_hidden));
1007                                         modified = false;
1008                                 }
1009                         }
1010
1011                         _line_numbers = lines.ToArray ();
1012
1013                         if (includesColumns) {
1014                                 for (int i = 0; i < _line_numbers.Length; ++i) {
1015                                         var ln = _line_numbers[i];
1016                                         if (ln.Row >= 0)
1017                                                 ln.Column = br.ReadLeb128 ();
1018                                 }
1019                         }
1020                         if (includesEnds) {
1021                                 for (int i = 0; i < _line_numbers.Length; ++i) {
1022                                         var ln = _line_numbers[i];
1023
1024                                         int row = br.ReadLeb128 ();
1025                                         if (row == 0xffffff) {
1026                                                 ln.EndRow = -1;
1027                                                 ln.EndColumn = -1;
1028                                         } else {
1029                                                 ln.EndRow = ln.Row + row;
1030                                                 ln.EndColumn = br.ReadLeb128 ();
1031                                         }
1032                                 }
1033                         }
1034                 }
1035
1036                 public bool GetMethodBounds (out LineNumberEntry start, out LineNumberEntry end)
1037                 {
1038                         if (_line_numbers.Length > 1) {
1039                                 start = _line_numbers [0];
1040                                 end = _line_numbers [_line_numbers.Length - 1];
1041                                 return true;
1042                         }
1043
1044                         start = LineNumberEntry.Null;
1045                         end = LineNumberEntry.Null;
1046                         return false;
1047                 }
1048         }
1049
1050         public class MethodEntry : IComparable
1051         {
1052                 #region This is actually written to the symbol file
1053                 public readonly int CompileUnitIndex;
1054                 public readonly int Token;
1055                 public readonly int NamespaceID;
1056
1057                 int DataOffset;
1058                 int LocalVariableTableOffset;
1059                 int LineNumberTableOffset;
1060                 int CodeBlockTableOffset;
1061                 int ScopeVariableTableOffset;
1062                 int RealNameOffset;
1063                 Flags flags;
1064                 #endregion
1065
1066                 int index;
1067
1068                 public Flags MethodFlags {
1069                         get { return flags; }
1070                 }
1071
1072                 public readonly CompileUnitEntry CompileUnit;
1073
1074                 LocalVariableEntry[] locals;
1075                 CodeBlockEntry[] code_blocks;
1076                 ScopeVariable[] scope_vars;
1077                 LineNumberTable lnt;
1078                 string real_name;
1079
1080                 public readonly MonoSymbolFile SymbolFile;
1081
1082                 public int Index {
1083                         get { return index; }
1084                         set { index = value; }
1085                 }
1086
1087                 [Flags]
1088                 public enum Flags
1089                 {
1090                         LocalNamesAmbiguous     = 1,
1091                         ColumnsInfoIncluded = 1 << 1,
1092                         EndInfoIncluded = 1 << 2
1093                 }
1094
1095                 public const int Size = 12;
1096
1097                 internal MethodEntry (MonoSymbolFile file, MyBinaryReader reader, int index)
1098                 {
1099                         this.SymbolFile = file;
1100                         this.index = index;
1101
1102                         Token = reader.ReadInt32 ();
1103                         DataOffset = reader.ReadInt32 ();
1104                         LineNumberTableOffset = reader.ReadInt32 ();
1105
1106                         long old_pos = reader.BaseStream.Position;
1107                         reader.BaseStream.Position = DataOffset;
1108
1109                         CompileUnitIndex = reader.ReadLeb128 ();
1110                         LocalVariableTableOffset = reader.ReadLeb128 ();
1111                         NamespaceID = reader.ReadLeb128 ();
1112
1113                         CodeBlockTableOffset = reader.ReadLeb128 ();
1114                         ScopeVariableTableOffset = reader.ReadLeb128 ();
1115
1116                         RealNameOffset = reader.ReadLeb128 ();
1117
1118                         flags = (Flags) reader.ReadLeb128 ();
1119
1120                         reader.BaseStream.Position = old_pos;
1121
1122                         CompileUnit = file.GetCompileUnit (CompileUnitIndex);
1123                 }
1124
1125                 internal MethodEntry (MonoSymbolFile file, CompileUnitEntry comp_unit,
1126                                       int token, ScopeVariable[] scope_vars,
1127                                       LocalVariableEntry[] locals, LineNumberEntry[] lines,
1128                                       CodeBlockEntry[] code_blocks, string real_name,
1129                                       Flags flags, int namespace_id)
1130                 {
1131                         this.SymbolFile = file;
1132                         this.real_name = real_name;
1133                         this.locals = locals;
1134                         this.code_blocks = code_blocks;
1135                         this.scope_vars = scope_vars;
1136                         this.flags = flags;
1137
1138                         index = -1;
1139
1140                         Token = token;
1141                         CompileUnitIndex = comp_unit.Index;
1142                         CompileUnit = comp_unit;
1143                         NamespaceID = namespace_id;
1144
1145                         CheckLineNumberTable (lines);
1146                         lnt = new LineNumberTable (file, lines);
1147                         file.NumLineNumbers += lines.Length;
1148
1149                         int num_locals = locals != null ? locals.Length : 0;
1150
1151                         if (num_locals <= 32) {
1152                                 // Most of the time, the O(n^2) factor is actually
1153                                 // less than the cost of allocating the hash table,
1154                                 // 32 is a rough number obtained through some testing.
1155                                 
1156                                 for (int i = 0; i < num_locals; i ++) {
1157                                         string nm = locals [i].Name;
1158                                         
1159                                         for (int j = i + 1; j < num_locals; j ++) {
1160                                                 if (locals [j].Name == nm) {
1161                                                         flags |= Flags.LocalNamesAmbiguous;
1162                                                         goto locals_check_done;
1163                                                 }
1164                                         }
1165                                 }
1166                         locals_check_done :
1167                                 ;
1168                         } else {
1169                                 var local_names = new Dictionary<string, LocalVariableEntry> ();
1170                                 foreach (LocalVariableEntry local in locals) {
1171                                         if (local_names.ContainsKey (local.Name)) {
1172                                                 flags |= Flags.LocalNamesAmbiguous;
1173                                                 break;
1174                                         }
1175                                         local_names.Add (local.Name, local);
1176                                 }
1177                         }
1178                 }
1179                 
1180                 static void CheckLineNumberTable (LineNumberEntry[] line_numbers)
1181                 {
1182                         int last_offset = -1;
1183                         int last_row = -1;
1184
1185                         if (line_numbers == null)
1186                                 return;
1187                         
1188                         for (int i = 0; i < line_numbers.Length; i++) {
1189                                 LineNumberEntry line = line_numbers [i];
1190
1191                                 if (line.Equals (LineNumberEntry.Null))
1192                                         throw new MonoSymbolFileException ();
1193
1194                                 if (line.Offset < last_offset)
1195                                         throw new MonoSymbolFileException ();
1196
1197                                 if (line.Offset > last_offset) {
1198                                         last_row = line.Row;
1199                                         last_offset = line.Offset;
1200                                 } else if (line.Row > last_row) {
1201                                         last_row = line.Row;
1202                                 }
1203                         }
1204                 }
1205
1206                 internal void Write (MyBinaryWriter bw)
1207                 {
1208                         if ((index <= 0) || (DataOffset == 0))
1209                                 throw new InvalidOperationException ();
1210
1211                         bw.Write (Token);
1212                         bw.Write (DataOffset);
1213                         bw.Write (LineNumberTableOffset);
1214                 }
1215
1216                 internal void WriteData (MonoSymbolFile file, MyBinaryWriter bw)
1217                 {
1218                         if (index <= 0)
1219                                 throw new InvalidOperationException ();
1220
1221                         LocalVariableTableOffset = (int) bw.BaseStream.Position;
1222                         int num_locals = locals != null ? locals.Length : 0;
1223                         bw.WriteLeb128 (num_locals);
1224                         for (int i = 0; i < num_locals; i++)
1225                                 locals [i].Write (file, bw);
1226                         file.LocalCount += num_locals;
1227
1228                         CodeBlockTableOffset = (int) bw.BaseStream.Position;
1229                         int num_code_blocks = code_blocks != null ? code_blocks.Length : 0;
1230                         bw.WriteLeb128 (num_code_blocks);
1231                         for (int i = 0; i < num_code_blocks; i++)
1232                                 code_blocks [i].Write (bw);
1233
1234                         ScopeVariableTableOffset = (int) bw.BaseStream.Position;
1235                         int num_scope_vars = scope_vars != null ? scope_vars.Length : 0;
1236                         bw.WriteLeb128 (num_scope_vars);
1237                         for (int i = 0; i < num_scope_vars; i++)
1238                                 scope_vars [i].Write (bw);
1239
1240                         if (real_name != null) {
1241                                 RealNameOffset = (int) bw.BaseStream.Position;
1242                                 bw.Write (real_name);
1243                         }
1244
1245                         foreach (var lne in lnt.LineNumbers) {
1246                                 if (lne.EndRow != -1 || lne.EndColumn != -1)
1247                                         flags |= Flags.EndInfoIncluded;
1248                         }
1249
1250                         LineNumberTableOffset = (int) bw.BaseStream.Position;
1251                         lnt.Write (file, bw, (flags & Flags.ColumnsInfoIncluded) != 0, (flags & Flags.EndInfoIncluded) != 0);
1252
1253                         DataOffset = (int) bw.BaseStream.Position;
1254
1255                         bw.WriteLeb128 (CompileUnitIndex);
1256                         bw.WriteLeb128 (LocalVariableTableOffset);
1257                         bw.WriteLeb128 (NamespaceID);
1258
1259                         bw.WriteLeb128 (CodeBlockTableOffset);
1260                         bw.WriteLeb128 (ScopeVariableTableOffset);
1261
1262                         bw.WriteLeb128 (RealNameOffset);
1263                         bw.WriteLeb128 ((int) flags);
1264                 }
1265
1266                 public void ReadAll ()
1267                 {
1268                         GetLineNumberTable ();
1269                         GetLocals ();
1270                         GetCodeBlocks ();
1271                         GetScopeVariables ();
1272                         GetRealName ();
1273                 }
1274
1275                 public LineNumberTable GetLineNumberTable ()
1276                 {
1277                         lock (SymbolFile) {
1278                                 if (lnt != null)
1279                                         return lnt;
1280
1281                                 if (LineNumberTableOffset == 0)
1282                                         return null;
1283
1284                                 MyBinaryReader reader = SymbolFile.BinaryReader;
1285                                 long old_pos = reader.BaseStream.Position;
1286                                 reader.BaseStream.Position = LineNumberTableOffset;
1287
1288                                 lnt = LineNumberTable.Read (SymbolFile, reader, (flags & Flags.ColumnsInfoIncluded) != 0, (flags & Flags.EndInfoIncluded) != 0);
1289
1290                                 reader.BaseStream.Position = old_pos;
1291                                 return lnt;
1292                         }
1293                 }
1294
1295                 public LocalVariableEntry[] GetLocals ()
1296                 {
1297                         lock (SymbolFile) {
1298                                 if (locals != null)
1299                                         return locals;
1300
1301                                 if (LocalVariableTableOffset == 0)
1302                                         return null;
1303
1304                                 MyBinaryReader reader = SymbolFile.BinaryReader;
1305                                 long old_pos = reader.BaseStream.Position;
1306                                 reader.BaseStream.Position = LocalVariableTableOffset;
1307
1308                                 int num_locals = reader.ReadLeb128 ();
1309                                 locals = new LocalVariableEntry [num_locals];
1310
1311                                 for (int i = 0; i < num_locals; i++)
1312                                         locals [i] = new LocalVariableEntry (SymbolFile, reader);
1313
1314                                 reader.BaseStream.Position = old_pos;
1315                                 return locals;
1316                         }
1317                 }
1318
1319                 public CodeBlockEntry[] GetCodeBlocks ()
1320                 {
1321                         lock (SymbolFile) {
1322                                 if (code_blocks != null)
1323                                         return code_blocks;
1324
1325                                 if (CodeBlockTableOffset == 0)
1326                                         return null;
1327
1328                                 MyBinaryReader reader = SymbolFile.BinaryReader;
1329                                 long old_pos = reader.BaseStream.Position;
1330                                 reader.BaseStream.Position = CodeBlockTableOffset;
1331
1332                                 int num_code_blocks = reader.ReadLeb128 ();
1333                                 code_blocks = new CodeBlockEntry [num_code_blocks];
1334
1335                                 for (int i = 0; i < num_code_blocks; i++)
1336                                         code_blocks [i] = new CodeBlockEntry (i, reader);
1337
1338                                 reader.BaseStream.Position = old_pos;
1339                                 return code_blocks;
1340                         }
1341                 }
1342
1343                 public ScopeVariable[] GetScopeVariables ()
1344                 {
1345                         lock (SymbolFile) {
1346                                 if (scope_vars != null)
1347                                         return scope_vars;
1348
1349                                 if (ScopeVariableTableOffset == 0)
1350                                         return null;
1351
1352                                 MyBinaryReader reader = SymbolFile.BinaryReader;
1353                                 long old_pos = reader.BaseStream.Position;
1354                                 reader.BaseStream.Position = ScopeVariableTableOffset;
1355
1356                                 int num_scope_vars = reader.ReadLeb128 ();
1357                                 scope_vars = new ScopeVariable [num_scope_vars];
1358
1359                                 for (int i = 0; i < num_scope_vars; i++)
1360                                         scope_vars [i] = new ScopeVariable (reader);
1361
1362                                 reader.BaseStream.Position = old_pos;
1363                                 return scope_vars;
1364                         }
1365                 }
1366
1367                 public string GetRealName ()
1368                 {
1369                         lock (SymbolFile) {
1370                                 if (real_name != null)
1371                                         return real_name;
1372
1373                                 if (RealNameOffset == 0)
1374                                         return null;
1375
1376                                 real_name = SymbolFile.BinaryReader.ReadString (RealNameOffset);
1377                                 return real_name;
1378                         }
1379                 }
1380
1381                 public int CompareTo (object obj)
1382                 {
1383                         MethodEntry method = (MethodEntry) obj;
1384
1385                         if (method.Token < Token)
1386                                 return 1;
1387                         else if (method.Token > Token)
1388                                 return -1;
1389                         else
1390                                 return 0;
1391                 }
1392
1393                 public override string ToString ()
1394                 {
1395                         return String.Format ("[Method {0}:{1:x}:{2}:{3}]",
1396                                               index, Token, CompileUnitIndex, CompileUnit);
1397                 }
1398         }
1399
1400         public struct NamespaceEntry
1401         {
1402                 #region This is actually written to the symbol file
1403                 public readonly string Name;
1404                 public readonly int Index;
1405                 public readonly int Parent;
1406                 public readonly string[] UsingClauses;
1407                 #endregion
1408
1409                 public NamespaceEntry (string name, int index, string[] using_clauses, int parent)
1410                 {
1411                         this.Name = name;
1412                         this.Index = index;
1413                         this.Parent = parent;
1414                         this.UsingClauses = using_clauses != null ? using_clauses : new string [0];
1415                 }
1416
1417                 internal NamespaceEntry (MonoSymbolFile file, MyBinaryReader reader)
1418                 {
1419                         Name = reader.ReadString ();
1420                         Index = reader.ReadLeb128 ();
1421                         Parent = reader.ReadLeb128 ();
1422
1423                         int count = reader.ReadLeb128 ();
1424                         UsingClauses = new string [count];
1425                         for (int i = 0; i < count; i++)
1426                                 UsingClauses [i] = reader.ReadString ();
1427                 }
1428
1429                 internal void Write (MonoSymbolFile file, MyBinaryWriter bw)
1430                 {
1431                         bw.Write (Name);
1432                         bw.WriteLeb128 (Index);
1433                         bw.WriteLeb128 (Parent);
1434                         bw.WriteLeb128 (UsingClauses.Length);
1435                         foreach (string uc in UsingClauses)
1436                                 bw.Write (uc);
1437                 }
1438
1439                 public override string ToString ()
1440                 {
1441                         return String.Format ("[Namespace {0}:{1}:{2}]", Name, Index, Parent);
1442                 }
1443         }
1444 }