2003-08-05 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / class / Mono.CSharp.Debugger / MonoSymbolTable.cs
1 //
2 // System.Diagnostics.SymbolStore/MonoSymbolTable.cs
3 //
4 // Author:
5 //   Martin Baulig (martin@gnome.org)
6 //
7 // (C) 2002 Ximian, Inc.  http://www.ximian.com
8 //
9
10 using System;
11 using System.Reflection;
12 using System.Reflection.Emit;
13 using System.Collections;
14 using System.Text;
15 using System.IO;
16         
17 namespace Mono.CSharp.Debugger
18 {
19         public struct OffsetTable
20         {
21                 public const int  Version = 35;
22                 public const long Magic   = 0x45e82623fd7fa614;
23
24                 public int TotalFileSize;
25                 public int DataSectionOffset;
26                 public int DataSectionSize;
27                 public int SourceCount;
28                 public int SourceTableOffset;
29                 public int SourceTableSize;
30                 public int MethodCount;
31                 public int MethodTableOffset;
32                 public int MethodTableSize;
33                 public int TypeCount;
34
35                 internal OffsetTable (BinaryReader reader)
36                 {
37                         TotalFileSize = reader.ReadInt32 ();
38                         DataSectionOffset = reader.ReadInt32 ();
39                         DataSectionSize = reader.ReadInt32 ();
40                         SourceCount = reader.ReadInt32 ();
41                         SourceTableOffset = reader.ReadInt32 ();
42                         SourceTableSize = reader.ReadInt32 ();
43                         MethodCount = reader.ReadInt32 ();
44                         MethodTableOffset = reader.ReadInt32 ();
45                         MethodTableSize = reader.ReadInt32 ();
46                         TypeCount = reader.ReadInt32 ();
47                 }
48
49                 internal void Write (BinaryWriter bw)
50                 {
51                         bw.Write (TotalFileSize);
52                         bw.Write (DataSectionOffset);
53                         bw.Write (DataSectionSize);
54                         bw.Write (SourceCount);
55                         bw.Write (SourceTableOffset);
56                         bw.Write (SourceTableSize);
57                         bw.Write (MethodCount);
58                         bw.Write (MethodTableOffset);
59                         bw.Write (MethodTableSize);
60                         bw.Write (TypeCount);
61                 }
62
63                 public override string ToString ()
64                 {
65                         return String.Format (
66                                 "OffsetTable [{0} - {1}:{2} - {3}:{4}:{5} - {6}:{7}:{8} - {9}]",
67                                 TotalFileSize, DataSectionOffset, DataSectionSize, SourceCount,
68                                 SourceTableOffset, SourceTableSize, MethodCount, MethodTableOffset,
69                                 MethodTableSize, TypeCount);
70                 }
71         }
72
73         public struct LineNumberEntry
74         {
75                 public readonly int Row;
76                 public readonly int Offset;
77
78                 public LineNumberEntry (int row, int offset)
79                 {
80                         this.Row = row;
81                         this.Offset = offset;
82                 }
83
84                 public static LineNumberEntry Null = new LineNumberEntry (0, 0);
85
86                 internal LineNumberEntry (BinaryReader reader)
87                 {
88                         Row = reader.ReadInt32 ();
89                         Offset = reader.ReadInt32 ();
90                 }
91
92                 internal void Write (BinaryWriter bw)
93                 {
94                         bw.Write (Row);
95                         bw.Write (Offset);
96                 }
97
98                 private class OffsetComparerClass : IComparer
99                 {
100                         public int Compare (object a, object b)
101                         {
102                                 LineNumberEntry l1 = (LineNumberEntry) a;
103                                 LineNumberEntry l2 = (LineNumberEntry) b;
104
105                                 if (l1.Offset < l2.Offset)
106                                         return -1;
107                                 else if (l1.Offset > l2.Offset)
108                                         return 1;
109                                 else
110                                         return 0;
111                         }
112                 }
113
114                 private class RowComparerClass : IComparer
115                 {
116                         public int Compare (object a, object b)
117                         {
118                                 LineNumberEntry l1 = (LineNumberEntry) a;
119                                 LineNumberEntry l2 = (LineNumberEntry) b;
120
121                                 if (l1.Row < l2.Row)
122                                         return -1;
123                                 else if (l1.Row > l2.Row)
124                                         return 1;
125                                 else
126                                         return 0;
127                         }
128                 }
129
130                 public static readonly IComparer OffsetComparer = new OffsetComparerClass ();
131                 public static readonly IComparer RowComparer = new RowComparerClass ();
132
133                 public override string ToString ()
134                 {
135                         return String.Format ("[Line {0}:{1}]", Row, Offset);
136                 }
137         }
138
139         public class LexicalBlockEntry
140         {
141                 public int Index;
142                 public int StartOffset;
143                 public int EndOffset;
144
145                 public LexicalBlockEntry (int index, int start_offset)
146                 {
147                         this.Index = index;
148                         this.StartOffset = start_offset;
149                 }
150
151                 internal LexicalBlockEntry (int index, BinaryReader reader)
152                 {
153                         this.Index = index;
154                         this.StartOffset = reader.ReadInt32 ();
155                         this.EndOffset = reader.ReadInt32 ();
156                 }
157
158                 public void Close (int end_offset)
159                 {
160                         this.EndOffset = end_offset;
161                 }
162
163                 internal void Write (BinaryWriter bw)
164                 {
165                         bw.Write (StartOffset);
166                         bw.Write (EndOffset);
167                 }
168
169                 public override string ToString ()
170                 {
171                         return String.Format ("[LexicalBlock {0}:{1}]", StartOffset, EndOffset);
172                 }
173         }
174
175         public struct LocalVariableEntry
176         {
177                 public readonly string Name;
178                 public readonly FieldAttributes Attributes;
179                 public readonly byte[] Signature;
180                 public readonly int BlockIndex;
181
182                 public LocalVariableEntry (string Name, FieldAttributes Attributes, byte[] Signature,
183                                            int BlockIndex)
184                 {
185                         this.Name = Name;
186                         this.Attributes = Attributes;
187                         this.Signature = Signature;
188                         this.BlockIndex = BlockIndex;
189                 }
190
191                 internal LocalVariableEntry (BinaryReader reader)
192                 {
193                         int name_length = reader.ReadInt32 ();
194                         byte[] name = reader.ReadBytes (name_length);
195                         Name = Encoding.UTF8.GetString (name);
196                         Attributes = (FieldAttributes) reader.ReadInt32 ();
197                         int sig_length = reader.ReadInt32 ();
198                         Signature = reader.ReadBytes (sig_length);
199                         BlockIndex = reader.ReadInt32 ();
200                 }
201
202                 internal void Write (MonoSymbolFile file, BinaryWriter bw)
203                 {
204                         file.WriteString (bw, Name);
205                         bw.Write ((int) Attributes);
206                         bw.Write ((int) Signature.Length);
207                         bw.Write (Signature);
208                         bw.Write (BlockIndex);
209                 }
210
211                 public override string ToString ()
212                 {
213                         return String.Format ("[LocalVariable {0}:{1}]", Name, Attributes);
214                 }
215         }
216
217         public class SourceFileEntry
218         {
219                 MonoSymbolFile file;
220                 string file_name;
221                 ArrayList methods;
222                 ArrayList namespaces;
223                 int index, count, name_offset, method_offset;
224                 int namespace_count, nstable_offset;
225                 bool creating;
226
227                 public static int Size {
228                         get { return 24; }
229                 }
230
231                 internal SourceFileEntry (MonoSymbolFile file, string file_name)
232                 {
233                         this.file = file;
234                         this.file_name = file_name;
235                         this.index = file.AddSource (this);
236
237                         creating = true;
238                         methods = new ArrayList ();
239                         namespaces = new ArrayList ();
240                 }
241
242                 public void DefineMethod (MethodBase method, int token, LocalVariableEntry[] locals,
243                                           LineNumberEntry[] lines, LexicalBlockEntry[] blocks,
244                                           int start, int end, int namespace_id)
245                 {
246                         if (!creating)
247                                 throw new InvalidOperationException ();
248
249                         MethodEntry entry = new MethodEntry (
250                                 file, this, method, token, locals, lines, blocks, start, end, namespace_id);
251
252                         methods.Add (entry);
253                         file.AddMethod (entry);
254                 }
255
256                 public int DefineNamespace (string name, string[] using_clauses, int parent)
257                 {
258                         if (!creating)
259                                 throw new InvalidOperationException ();
260
261                         int index = file.GetNextNamespaceIndex ();
262                         NamespaceEntry ns = new NamespaceEntry (name, index, using_clauses, parent);
263                         namespaces.Add (ns);
264                         return index;
265                 }
266
267                 internal void WriteData (BinaryWriter bw)
268                 {
269                         name_offset = (int) bw.BaseStream.Position;
270                         file.WriteString (bw, file_name);
271
272                         ArrayList list = new ArrayList ();
273                         foreach (MethodEntry entry in methods)
274                                 list.Add (entry.Write (file, bw));
275                         list.Sort ();
276                         count = list.Count;
277
278                         method_offset = (int) bw.BaseStream.Position;
279                         foreach (MethodSourceEntry method in list)
280                                 method.Write (bw);
281
282                         namespace_count = namespaces.Count;
283                         nstable_offset = (int) bw.BaseStream.Position;
284                         foreach (NamespaceEntry ns in namespaces)
285                                 ns.Write (file, bw);
286                 }
287
288                 internal void Write (BinaryWriter bw)
289                 {
290                         bw.Write (index);
291                         bw.Write (count);
292                         bw.Write (namespace_count);
293                         bw.Write (name_offset);
294                         bw.Write (method_offset);
295                         bw.Write (nstable_offset);
296                 }
297
298                 internal SourceFileEntry (MonoSymbolFile file, BinaryReader reader)
299                 {
300                         this.file = file;
301
302                         index = reader.ReadInt32 ();
303                         count = reader.ReadInt32 ();
304                         namespace_count = reader.ReadInt32 ();
305                         name_offset = reader.ReadInt32 ();
306                         method_offset = reader.ReadInt32 ();
307                         nstable_offset = reader.ReadInt32 ();
308
309                         file_name = file.ReadString (name_offset);
310                 }
311
312                 public int Index {
313                         get { return index; }
314                 }
315
316                 public string FileName {
317                         get { return file_name; }
318                 }
319
320                 public MethodSourceEntry[] Methods {
321                         get {
322                                 if (creating)
323                                         throw new InvalidOperationException ();
324
325                                 BinaryReader reader = file.BinaryReader;
326                                 int old_pos = (int) reader.BaseStream.Position;
327
328                                 reader.BaseStream.Position = method_offset;
329                                 ArrayList list = new ArrayList ();
330                                 for (int i = 0; i < count; i ++)
331                                         list.Add (new MethodSourceEntry (reader));
332                                 reader.BaseStream.Position = old_pos;
333
334                                 MethodSourceEntry[] retval = new MethodSourceEntry [count];
335                                 list.CopyTo (retval, 0);
336                                 return retval;
337                         }
338                 }
339
340                 public override string ToString ()
341                 {
342                         return String.Format ("SourceFileEntry ({0}:{1}:{2})", index, file_name, count);
343                 }
344         }
345
346         public struct MethodSourceEntry : IComparable
347         {
348                 public readonly int Index;
349                 public readonly int FileOffset;
350                 public readonly int StartRow;
351                 public readonly int EndRow;
352
353                 public MethodSourceEntry (int index, int file_offset, int start, int end)
354                 {
355                         this.Index = index;
356                         this.FileOffset = file_offset;
357                         this.StartRow = start;
358                         this.EndRow = end;
359                 }
360
361                 internal MethodSourceEntry (BinaryReader reader)
362                 {
363                         Index = reader.ReadInt32 ();
364                         FileOffset = reader.ReadInt32 ();
365                         StartRow = reader.ReadInt32 ();
366                         EndRow = reader.ReadInt32 ();
367                 }
368
369                 public static int Size {
370                         get { return 16; }
371                 }
372
373                 internal void Write (BinaryWriter bw)
374                 {
375                         bw.Write (Index);
376                         bw.Write (FileOffset);
377                         bw.Write (StartRow);
378                         bw.Write (EndRow);
379                 }
380
381                 public int CompareTo (object obj)
382                 {
383                         MethodSourceEntry method = (MethodSourceEntry) obj;
384
385                         if (method.StartRow < StartRow)
386                                 return -1;
387                         else if (method.StartRow > StartRow)
388                                 return 1;
389                         else
390                                 return 0;
391                 }
392
393                 public override string ToString ()
394                 {
395                         return String.Format ("MethodSourceEntry ({0}:{1}:{2}:{3})",
396                                               Index, FileOffset, StartRow, EndRow);
397                 }
398         }
399
400         public struct MethodIndexEntry
401         {
402                 public readonly int FileOffset;
403                 public readonly int FullNameOffset;
404                 public readonly int Token;
405
406                 public static int Size {
407                         get { return 12; }
408                 }
409
410                 public MethodIndexEntry (int offset, int name_offset, int token)
411                 {
412                         this.FileOffset = offset;
413                         this.FullNameOffset = name_offset;
414                         this.Token = token;
415                 }
416
417                 internal MethodIndexEntry (BinaryReader reader)
418                 {
419                         FileOffset = reader.ReadInt32 ();
420                         FullNameOffset = reader.ReadInt32 ();
421                         Token = reader.ReadInt32 ();
422                 }
423
424                 internal void Write (BinaryWriter bw)
425                 {
426                         bw.Write (FileOffset);
427                         bw.Write (FullNameOffset);
428                         bw.Write (Token);
429                 }
430
431                 public override string ToString ()
432                 {
433                         return String.Format ("MethodIndexEntry ({0}:{1}:{2:x})",
434                                               FileOffset, FullNameOffset, Token);
435                 }
436         }
437
438         public class MethodEntry
439         {
440                 #region This is actually written to the symbol file
441                 public readonly int SourceFileIndex;
442                 public readonly int Token;
443                 public readonly int StartRow;
444                 public readonly int EndRow;
445                 public readonly int ClassTypeIndex;
446                 public readonly int NumParameters;
447                 public readonly int NumLocals;
448                 public readonly int NumLineNumbers;
449                 public readonly int NamespaceID;
450                 public readonly bool LocalNamesAmbiguous;
451
452                 int NameOffset;
453                 int FullNameOffset;
454                 int TypeIndexTableOffset;
455                 int LocalVariableTableOffset;
456                 int LineNumberTableOffset;
457                 int NumLexicalBlocks;
458                 int LexicalBlockTableOffset;
459                 #endregion
460
461                 int file_offset;
462                 string name;
463                 string full_name;
464                 MethodIndexEntry index_entry;
465
466                 public readonly int Index;
467                 public readonly SourceFileEntry SourceFile;
468                 public readonly LineNumberEntry[] LineNumbers;
469                 public readonly int[] ParamTypeIndices;
470                 public readonly int[] LocalTypeIndices;
471                 public readonly LocalVariableEntry[] Locals;
472                 public readonly Type[] LocalTypes;
473                 public readonly LexicalBlockEntry[] LexicalBlocks;
474
475                 public readonly MonoSymbolFile SymbolFile;
476
477                 public static int Size {
478                         get { return 52; }
479                 }
480
481                 public string Name {
482                         get { return name; }
483                 }
484
485                 public string FullName {
486                         get { return full_name; }
487                 }
488
489                 public MethodBase MethodBase {
490                         get { return SymbolFile.Assembly.MonoDebugger_GetMethod (Token); }
491                 }
492
493                 internal MethodEntry (MonoSymbolFile file, BinaryReader reader, int index)
494                 {
495                         this.SymbolFile = file;
496                         this.Index = index;
497                         SourceFileIndex = reader.ReadInt32 ();
498                         Token = reader.ReadInt32 ();
499                         StartRow = reader.ReadInt32 ();
500                         EndRow = reader.ReadInt32 ();
501                         ClassTypeIndex = reader.ReadInt32 ();
502                         NumParameters = reader.ReadInt32 ();
503                         NumLocals = reader.ReadInt32 ();
504                         NumLineNumbers = reader.ReadInt32 ();
505                         NameOffset = reader.ReadInt32 ();
506                         FullNameOffset = reader.ReadInt32 ();
507                         TypeIndexTableOffset = reader.ReadInt32 ();
508                         LocalVariableTableOffset = reader.ReadInt32 ();
509                         LineNumberTableOffset = reader.ReadInt32 ();
510                         NumLexicalBlocks = reader.ReadInt32 ();
511                         LexicalBlockTableOffset = reader.ReadInt32 ();
512                         NamespaceID = reader.ReadInt32 ();
513                         LocalNamesAmbiguous = reader.ReadInt32 () != 0;
514
515                         name = file.ReadString (NameOffset);
516                         full_name = file.ReadString (FullNameOffset);
517
518                         SourceFile = file.GetSourceFile (SourceFileIndex);
519
520                         if (LineNumberTableOffset != 0) {
521                                 long old_pos = reader.BaseStream.Position;
522                                 reader.BaseStream.Position = LineNumberTableOffset;
523
524                                 LineNumbers = new LineNumberEntry [NumLineNumbers];
525
526                                 for (int i = 0; i < NumLineNumbers; i++)
527                                         LineNumbers [i] = new LineNumberEntry (reader);
528
529                                 reader.BaseStream.Position = old_pos;
530                         }
531
532                         if (LocalVariableTableOffset != 0) {
533                                 long old_pos = reader.BaseStream.Position;
534                                 reader.BaseStream.Position = LocalVariableTableOffset;
535
536                                 Locals = new LocalVariableEntry [NumLocals];
537                                 LocalTypes = new Type [NumLocals];
538
539                                 Assembly ass = file.Assembly;
540
541                                 for (int i = 0; i < NumLocals; i++) {
542                                         Locals [i] = new LocalVariableEntry (reader);
543                                         LocalTypes [i] = ass.MonoDebugger_GetLocalTypeFromSignature (
544                                                 Locals [i].Signature);
545                                 }
546
547                                 reader.BaseStream.Position = old_pos;
548                         }
549
550                         if (TypeIndexTableOffset != 0) {
551                                 long old_pos = reader.BaseStream.Position;
552                                 reader.BaseStream.Position = TypeIndexTableOffset;
553
554                                 ParamTypeIndices = new int [NumParameters];
555                                 LocalTypeIndices = new int [NumLocals];
556
557                                 for (int i = 0; i < NumParameters; i++)
558                                         ParamTypeIndices [i] = reader.ReadInt32 ();
559                                 for (int i = 0; i < NumLocals; i++)
560                                         LocalTypeIndices [i] = reader.ReadInt32 ();
561
562                                 reader.BaseStream.Position = old_pos;
563                         }
564
565                         if (LexicalBlockTableOffset != 0) {
566                                 long old_pos = reader.BaseStream.Position;
567                                 reader.BaseStream.Position = LexicalBlockTableOffset;
568
569                                 LexicalBlocks = new LexicalBlockEntry [NumLexicalBlocks];
570                                 for (int i = 0; i < NumLexicalBlocks; i++)
571                                         LexicalBlocks [i] = new LexicalBlockEntry (i, reader);
572
573                                 reader.BaseStream.Position = old_pos;
574                         }
575                 }
576
577                 internal MethodEntry (MonoSymbolFile file, SourceFileEntry source, MethodBase method,
578                                       int token, LocalVariableEntry[] locals, LineNumberEntry[] lines,
579                                       LexicalBlockEntry[] blocks, int start_row, int end_row,
580                                       int namespace_id)
581                 {
582                         this.SymbolFile = file;
583                         Index = file.GetNextMethodIndex ();
584
585                         Token = token;
586                         SourceFileIndex = source.Index;
587                         SourceFile = source;
588                         StartRow = start_row;
589                         EndRow = end_row;
590                         NamespaceID = namespace_id;
591                         LexicalBlocks = blocks;
592                         NumLexicalBlocks = LexicalBlocks.Length;
593
594                         LineNumbers = BuildLineNumberTable (lines);
595                         NumLineNumbers = LineNumbers.Length;
596
597                         ParameterInfo[] parameters = method.GetParameters ();
598                         if (parameters == null)
599                                 parameters = new ParameterInfo [0];
600
601                         StringBuilder sb = new StringBuilder ();
602                         sb.Append (method.DeclaringType.FullName);
603                         sb.Append (".");
604                         sb.Append (method.Name);
605                         sb.Append ("(");
606                         for (int i = 0; i < parameters.Length; i++) {
607                                 if (i > 0)
608                                         sb.Append (",");
609                                 sb.Append (parameters [i].ParameterType.FullName);
610                         }
611                         sb.Append (")");
612
613                         name = method.Name;
614                         full_name = sb.ToString ();
615
616                         NumParameters = parameters.Length;
617                         ParamTypeIndices = new int [NumParameters];
618                         for (int i = 0; i < NumParameters; i++)
619                                 ParamTypeIndices [i] = file.DefineType (parameters [i].ParameterType);
620
621                         NumLocals = locals.Length;
622                         Locals = locals;
623
624                         Hashtable local_names = new Hashtable ();
625                         foreach (LocalVariableEntry local in locals) {
626                                 if (local_names.Contains (local.Name)) {
627                                         LocalNamesAmbiguous = true;
628                                         break;
629                                 }
630                                 local_names.Add (local.Name, local);
631                         }
632
633                         LocalTypeIndices = new int [NumLocals];
634                         for (int i = 0; i < NumLocals; i++)
635                                 LocalTypeIndices [i] = file.GetNextTypeIndex ();
636
637                         ClassTypeIndex = file.DefineType (method.ReflectedType);
638                 }
639
640                 LineNumberEntry[] BuildLineNumberTable (LineNumberEntry[] line_numbers)
641                 {
642                         ArrayList list = new ArrayList ();
643                         int last_offset = -1;
644                         int last_row = -1;
645
646                         for (int i = 0; i < line_numbers.Length; i++) {
647                                 LineNumberEntry line = (LineNumberEntry) line_numbers [i];
648
649                                 if (line.Offset > last_offset) {
650                                         if (last_row >= 0)
651                                                 list.Add (new LineNumberEntry (last_row, last_offset));
652                                         last_row = line.Row;
653                                         last_offset = line.Offset;
654                                 } else if (line.Row > last_row) {
655                                         last_row = line.Row;
656                                 }
657                         }
658
659                         if (last_row >= 0)
660                                 list.Add (new LineNumberEntry (last_row, last_offset));
661
662                         LineNumberEntry[] retval = new LineNumberEntry [list.Count];
663                         list.CopyTo (retval, 0);
664                         return retval;
665                 }
666
667                 internal MethodSourceEntry Write (MonoSymbolFile file, BinaryWriter bw)
668                 {
669                         NameOffset = (int) bw.BaseStream.Position;
670                         file.WriteString (bw, name);
671
672                         FullNameOffset = (int) bw.BaseStream.Position;
673                         file.WriteString (bw, full_name);
674
675                         TypeIndexTableOffset = (int) bw.BaseStream.Position;
676
677                         for (int i = 0; i < NumParameters; i++)
678                                 bw.Write (ParamTypeIndices [i]);
679                         for (int i = 0; i < NumLocals; i++)
680                                 bw.Write (LocalTypeIndices [i]);
681
682                         LocalVariableTableOffset = (int) bw.BaseStream.Position;
683                         for (int i = 0; i < NumLocals; i++)
684                                 Locals [i].Write (file, bw);
685                         file.LocalCount += NumLocals;
686
687                         LineNumberTableOffset = (int) bw.BaseStream.Position;
688                         for (int i = 0; i < NumLineNumbers; i++)
689                                 LineNumbers [i].Write (bw);
690                         file.LineNumberCount += NumLineNumbers;
691
692                         LexicalBlockTableOffset = (int) bw.BaseStream.Position;
693                         for (int i = 0; i < NumLexicalBlocks; i++)
694                                 LexicalBlocks [i].Write (bw);
695                         file_offset = (int) bw.BaseStream.Position;
696
697                         index_entry = new MethodIndexEntry (file_offset, FullNameOffset, Token);
698
699                         bw.Write (SourceFileIndex);
700                         bw.Write (Token);
701                         bw.Write (StartRow);
702                         bw.Write (EndRow);
703                         bw.Write (ClassTypeIndex);
704                         bw.Write (NumParameters);
705                         bw.Write (NumLocals);
706                         bw.Write (NumLineNumbers);
707                         bw.Write (NameOffset);
708                         bw.Write (FullNameOffset);
709                         bw.Write (TypeIndexTableOffset);
710                         bw.Write (LocalVariableTableOffset);
711                         bw.Write (LineNumberTableOffset);
712                         bw.Write (NumLexicalBlocks);
713                         bw.Write (LexicalBlockTableOffset);
714                         bw.Write (NamespaceID);
715                         bw.Write (LocalNamesAmbiguous ? 1 : 0);
716
717                         return new MethodSourceEntry (Index, file_offset, StartRow, EndRow);
718                 }
719
720                 internal void WriteIndex (BinaryWriter bw)
721                 {
722                         index_entry.Write (bw);
723                 }
724
725                 public override string ToString ()
726                 {
727                         return String.Format ("[Method {0}:{1}:{2}:{3}:{4} - {7}:{8}:{9}:{10} - {5} - {6}]",
728                                               Index, Token, SourceFileIndex, StartRow, EndRow,
729                                               SourceFile, FullName, ClassTypeIndex, NumParameters,
730                                               NumLocals, NumLineNumbers);
731                 }
732         }
733
734         public struct NamespaceEntry
735         {
736                 public readonly string Name;
737                 public readonly int Index;
738                 public readonly int Parent;
739                 public readonly string[] UsingClauses;
740
741                 public NamespaceEntry (string name, int index, string[] using_clauses, int parent)
742                 {
743                         this.Name = name;
744                         this.Index = index;
745                         this.Parent = parent;
746                         this.UsingClauses = using_clauses != null ? using_clauses : new string [0];
747                 }
748
749                 internal void Write (MonoSymbolFile file, BinaryWriter bw)
750                 {
751                         file.WriteString (bw, Name);
752                         bw.Write (Index);
753                         bw.Write (Parent);
754                         bw.Write (UsingClauses.Length);
755                         foreach (string uc in UsingClauses)
756                                 file.WriteString (bw, uc);
757                 }
758
759                 public override string ToString ()
760                 {
761                         return String.Format ("[Namespace {0}:{1}:{2}]", Name, Index, Parent);
762                 }
763         }
764 }