2 // System.Diagnostics.SymbolStore/MonoSymbolTable.cs
5 // Martin Baulig (martin@gnome.org)
7 // (C) 2002 Ximian, Inc. http://www.ximian.com
11 using System.Reflection;
12 using System.Reflection.Emit;
13 using System.Collections;
17 namespace Mono.CSharp.Debugger
19 public struct OffsetTable
21 public const int Version = 34;
22 public const long Magic = 0x45e82623fd7fa614;
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;
35 internal OffsetTable (BinaryReader reader)
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 ();
49 internal void Write (BinaryWriter bw)
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);
63 public override string ToString ()
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);
73 public struct LineNumberEntry
75 public readonly int Row;
76 public readonly int Offset;
78 public LineNumberEntry (int row, int offset)
84 public static LineNumberEntry Null = new LineNumberEntry (0, 0);
86 internal LineNumberEntry (BinaryReader reader)
88 Row = reader.ReadInt32 ();
89 Offset = reader.ReadInt32 ();
92 internal void Write (BinaryWriter bw)
98 private class OffsetComparerClass : IComparer
100 public int Compare (object a, object b)
102 LineNumberEntry l1 = (LineNumberEntry) a;
103 LineNumberEntry l2 = (LineNumberEntry) b;
105 if (l1.Offset < l2.Offset)
107 else if (l1.Offset > l2.Offset)
114 private class RowComparerClass : IComparer
116 public int Compare (object a, object b)
118 LineNumberEntry l1 = (LineNumberEntry) a;
119 LineNumberEntry l2 = (LineNumberEntry) b;
123 else if (l1.Row > l2.Row)
130 public static readonly IComparer OffsetComparer = new OffsetComparerClass ();
131 public static readonly IComparer RowComparer = new RowComparerClass ();
133 public override string ToString ()
135 return String.Format ("[Line {0}:{1}]", Row, Offset);
139 public class LexicalBlockEntry
142 public int StartOffset;
143 public int EndOffset;
145 public LexicalBlockEntry (int index, int start_offset)
148 this.StartOffset = start_offset;
151 internal LexicalBlockEntry (int index, BinaryReader reader)
154 this.StartOffset = reader.ReadInt32 ();
155 this.EndOffset = reader.ReadInt32 ();
158 public void Close (int end_offset)
160 this.EndOffset = end_offset;
163 internal void Write (BinaryWriter bw)
165 bw.Write (StartOffset);
166 bw.Write (EndOffset);
169 public override string ToString ()
171 return String.Format ("[LexicalBlock {0}:{1}]", StartOffset, EndOffset);
175 public struct LocalVariableEntry
177 public readonly string Name;
178 public readonly FieldAttributes Attributes;
179 public readonly byte[] Signature;
180 public readonly int BlockIndex;
182 public LocalVariableEntry (string Name, FieldAttributes Attributes, byte[] Signature,
186 this.Attributes = Attributes;
187 this.Signature = Signature;
188 this.BlockIndex = BlockIndex;
191 internal LocalVariableEntry (BinaryReader reader)
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 ();
202 internal void Write (MonoSymbolFile file, BinaryWriter bw)
204 file.WriteString (bw, Name);
205 bw.Write ((int) Attributes);
206 bw.Write ((int) Signature.Length);
207 bw.Write (Signature);
208 bw.Write (BlockIndex);
211 public override string ToString ()
213 return String.Format ("[LocalVariable {0}:{1}]", Name, Attributes);
217 public class SourceFileEntry
222 ArrayList namespaces;
223 int index, count, name_offset, method_offset;
224 int namespace_count, nstable_offset;
227 public static int Size {
231 internal SourceFileEntry (MonoSymbolFile file, string file_name)
234 this.file_name = file_name;
235 this.index = file.AddSource (this);
238 methods = new ArrayList ();
239 namespaces = new ArrayList ();
242 public void DefineMethod (MethodBase method, int token, LocalVariableEntry[] locals,
243 LineNumberEntry[] lines, LexicalBlockEntry[] blocks,
244 int start, int end, int namespace_id)
247 throw new InvalidOperationException ();
249 MethodEntry entry = new MethodEntry (
250 file, this, method, token, locals, lines, blocks, start, end, namespace_id);
253 file.AddMethod (entry);
256 public int DefineNamespace (string name, string[] using_clauses, int parent)
259 throw new InvalidOperationException ();
261 int index = file.GetNextNamespaceIndex ();
262 NamespaceEntry ns = new NamespaceEntry (name, index, using_clauses, parent);
267 internal void WriteData (BinaryWriter bw)
269 name_offset = (int) bw.BaseStream.Position;
270 file.WriteString (bw, file_name);
272 ArrayList list = new ArrayList ();
273 foreach (MethodEntry entry in methods)
274 list.Add (entry.Write (file, bw));
278 method_offset = (int) bw.BaseStream.Position;
279 foreach (MethodSourceEntry method in list)
282 namespace_count = namespaces.Count;
283 nstable_offset = (int) bw.BaseStream.Position;
284 foreach (NamespaceEntry ns in namespaces)
288 internal void Write (BinaryWriter bw)
292 bw.Write (namespace_count);
293 bw.Write (name_offset);
294 bw.Write (method_offset);
295 bw.Write (nstable_offset);
298 internal SourceFileEntry (MonoSymbolFile file, BinaryReader reader)
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 ();
309 file_name = file.ReadString (name_offset);
313 get { return index; }
316 public string FileName {
317 get { return file_name; }
320 public MethodSourceEntry[] Methods {
323 throw new InvalidOperationException ();
325 BinaryReader reader = file.BinaryReader;
326 int old_pos = (int) reader.BaseStream.Position;
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;
334 MethodSourceEntry[] retval = new MethodSourceEntry [count];
335 list.CopyTo (retval, 0);
340 public override string ToString ()
342 return String.Format ("SourceFileEntry ({0}:{1}:{2})", index, file_name, count);
346 public struct MethodSourceEntry : IComparable
348 public readonly int Index;
349 public readonly int FileOffset;
350 public readonly int StartRow;
351 public readonly int EndRow;
353 public MethodSourceEntry (int index, int file_offset, int start, int end)
356 this.FileOffset = file_offset;
357 this.StartRow = start;
361 internal MethodSourceEntry (BinaryReader reader)
363 Index = reader.ReadInt32 ();
364 FileOffset = reader.ReadInt32 ();
365 StartRow = reader.ReadInt32 ();
366 EndRow = reader.ReadInt32 ();
369 public static int Size {
373 internal void Write (BinaryWriter bw)
376 bw.Write (FileOffset);
381 public int CompareTo (object obj)
383 MethodSourceEntry method = (MethodSourceEntry) obj;
385 if (method.StartRow < StartRow)
387 else if (method.StartRow > StartRow)
393 public override string ToString ()
395 return String.Format ("MethodSourceEntry ({0}:{1}:{2}:{3})",
396 Index, FileOffset, StartRow, EndRow);
400 public struct MethodIndexEntry
402 public readonly int FileOffset;
403 public readonly int FullNameOffset;
404 public readonly int Token;
406 public static int Size {
410 public MethodIndexEntry (int offset, int name_offset, int token)
412 this.FileOffset = offset;
413 this.FullNameOffset = name_offset;
417 internal MethodIndexEntry (BinaryReader reader)
419 FileOffset = reader.ReadInt32 ();
420 FullNameOffset = reader.ReadInt32 ();
421 Token = reader.ReadInt32 ();
424 internal void Write (BinaryWriter bw)
426 bw.Write (FileOffset);
427 bw.Write (FullNameOffset);
431 public override string ToString ()
433 return String.Format ("MethodIndexEntry ({0}:{1}:{2:x})",
434 FileOffset, FullNameOffset, Token);
438 public class MethodEntry
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;
453 int TypeIndexTableOffset;
454 int LocalVariableTableOffset;
455 int LineNumberTableOffset;
456 int NumLexicalBlocks;
457 int LexicalBlockTableOffset;
464 MethodIndexEntry index_entry;
466 public readonly SourceFileEntry SourceFile;
467 public readonly LineNumberEntry[] LineNumbers;
468 public readonly int[] ParamTypeIndices;
469 public readonly int[] LocalTypeIndices;
470 public readonly LocalVariableEntry[] Locals;
471 public readonly Type[] LocalTypes;
472 public readonly LexicalBlockEntry[] LexicalBlocks;
474 public readonly MonoSymbolFile SymbolFile;
476 public static int Size {
484 public string FullName {
485 get { return full_name; }
488 public MethodBase MethodBase {
489 get { return SymbolFile.Assembly.MonoDebugger_GetMethod (Token); }
492 internal MethodEntry (MonoSymbolFile file, BinaryReader reader, int index)
494 this.SymbolFile = file;
496 SourceFileIndex = reader.ReadInt32 ();
497 Token = reader.ReadInt32 ();
498 StartRow = reader.ReadInt32 ();
499 EndRow = reader.ReadInt32 ();
500 ClassTypeIndex = reader.ReadInt32 ();
501 NumParameters = reader.ReadInt32 ();
502 NumLocals = reader.ReadInt32 ();
503 NumLineNumbers = reader.ReadInt32 ();
504 NameOffset = reader.ReadInt32 ();
505 FullNameOffset = reader.ReadInt32 ();
506 TypeIndexTableOffset = reader.ReadInt32 ();
507 LocalVariableTableOffset = reader.ReadInt32 ();
508 LineNumberTableOffset = reader.ReadInt32 ();
509 NumLexicalBlocks = reader.ReadInt32 ();
510 LexicalBlockTableOffset = reader.ReadInt32 ();
511 NamespaceID = reader.ReadInt32 ();
513 name = file.ReadString (NameOffset);
514 full_name = file.ReadString (FullNameOffset);
516 SourceFile = file.GetSourceFile (SourceFileIndex);
518 if (LineNumberTableOffset != 0) {
519 long old_pos = reader.BaseStream.Position;
520 reader.BaseStream.Position = LineNumberTableOffset;
522 LineNumbers = new LineNumberEntry [NumLineNumbers];
524 for (int i = 0; i < NumLineNumbers; i++)
525 LineNumbers [i] = new LineNumberEntry (reader);
527 reader.BaseStream.Position = old_pos;
530 if (LocalVariableTableOffset != 0) {
531 long old_pos = reader.BaseStream.Position;
532 reader.BaseStream.Position = LocalVariableTableOffset;
534 Locals = new LocalVariableEntry [NumLocals];
535 LocalTypes = new Type [NumLocals];
537 Assembly ass = file.Assembly;
539 for (int i = 0; i < NumLocals; i++) {
540 Locals [i] = new LocalVariableEntry (reader);
541 LocalTypes [i] = ass.MonoDebugger_GetLocalTypeFromSignature (
542 Locals [i].Signature);
545 reader.BaseStream.Position = old_pos;
548 if (TypeIndexTableOffset != 0) {
549 long old_pos = reader.BaseStream.Position;
550 reader.BaseStream.Position = TypeIndexTableOffset;
552 ParamTypeIndices = new int [NumParameters];
553 LocalTypeIndices = new int [NumLocals];
555 for (int i = 0; i < NumParameters; i++)
556 ParamTypeIndices [i] = reader.ReadInt32 ();
557 for (int i = 0; i < NumLocals; i++)
558 LocalTypeIndices [i] = reader.ReadInt32 ();
560 reader.BaseStream.Position = old_pos;
563 if (LexicalBlockTableOffset != 0) {
564 long old_pos = reader.BaseStream.Position;
565 reader.BaseStream.Position = LexicalBlockTableOffset;
567 LexicalBlocks = new LexicalBlockEntry [NumLexicalBlocks];
568 for (int i = 0; i < NumLexicalBlocks; i++)
569 LexicalBlocks [i] = new LexicalBlockEntry (i, reader);
571 reader.BaseStream.Position = old_pos;
575 internal MethodEntry (MonoSymbolFile file, SourceFileEntry source, MethodBase method,
576 int token, LocalVariableEntry[] locals, LineNumberEntry[] lines,
577 LexicalBlockEntry[] blocks, int start_row, int end_row,
580 this.SymbolFile = file;
581 index = file.GetNextMethodIndex ();
584 SourceFileIndex = source.Index;
586 StartRow = start_row;
588 NamespaceID = namespace_id;
589 LexicalBlocks = blocks;
590 NumLexicalBlocks = LexicalBlocks.Length;
592 LineNumbers = BuildLineNumberTable (lines);
593 NumLineNumbers = LineNumbers.Length;
595 ParameterInfo[] parameters = method.GetParameters ();
596 if (parameters == null)
597 parameters = new ParameterInfo [0];
599 StringBuilder sb = new StringBuilder ();
600 sb.Append (method.DeclaringType.FullName);
602 sb.Append (method.Name);
604 for (int i = 0; i < parameters.Length; i++) {
607 sb.Append (parameters [i].ParameterType.FullName);
612 full_name = sb.ToString ();
614 NumParameters = parameters.Length;
615 ParamTypeIndices = new int [NumParameters];
616 for (int i = 0; i < NumParameters; i++)
617 ParamTypeIndices [i] = file.DefineType (parameters [i].ParameterType);
619 NumLocals = locals.Length;
622 LocalTypeIndices = new int [NumLocals];
623 for (int i = 0; i < NumLocals; i++)
624 LocalTypeIndices [i] = file.GetNextTypeIndex ();
626 ClassTypeIndex = file.DefineType (method.ReflectedType);
629 LineNumberEntry[] BuildLineNumberTable (LineNumberEntry[] line_numbers)
631 ArrayList list = new ArrayList ();
632 int last_offset = -1;
635 for (int i = 0; i < line_numbers.Length; i++) {
636 LineNumberEntry line = (LineNumberEntry) line_numbers [i];
638 if (line.Offset > last_offset) {
640 list.Add (new LineNumberEntry (last_row, last_offset));
642 last_offset = line.Offset;
643 } else if (line.Row > last_row) {
649 list.Add (new LineNumberEntry (last_row, last_offset));
651 LineNumberEntry[] retval = new LineNumberEntry [list.Count];
652 list.CopyTo (retval, 0);
656 internal MethodSourceEntry Write (MonoSymbolFile file, BinaryWriter bw)
658 NameOffset = (int) bw.BaseStream.Position;
659 file.WriteString (bw, name);
661 FullNameOffset = (int) bw.BaseStream.Position;
662 file.WriteString (bw, full_name);
664 TypeIndexTableOffset = (int) bw.BaseStream.Position;
666 for (int i = 0; i < NumParameters; i++)
667 bw.Write (ParamTypeIndices [i]);
668 for (int i = 0; i < NumLocals; i++)
669 bw.Write (LocalTypeIndices [i]);
671 LocalVariableTableOffset = (int) bw.BaseStream.Position;
672 for (int i = 0; i < NumLocals; i++)
673 Locals [i].Write (file, bw);
674 file.LocalCount += NumLocals;
676 LineNumberTableOffset = (int) bw.BaseStream.Position;
677 for (int i = 0; i < NumLineNumbers; i++)
678 LineNumbers [i].Write (bw);
679 file.LineNumberCount += NumLineNumbers;
681 LexicalBlockTableOffset = (int) bw.BaseStream.Position;
682 for (int i = 0; i < NumLexicalBlocks; i++)
683 LexicalBlocks [i].Write (bw);
684 file_offset = (int) bw.BaseStream.Position;
686 index_entry = new MethodIndexEntry (file_offset, FullNameOffset, Token);
688 bw.Write (SourceFileIndex);
692 bw.Write (ClassTypeIndex);
693 bw.Write (NumParameters);
694 bw.Write (NumLocals);
695 bw.Write (NumLineNumbers);
696 bw.Write (NameOffset);
697 bw.Write (FullNameOffset);
698 bw.Write (TypeIndexTableOffset);
699 bw.Write (LocalVariableTableOffset);
700 bw.Write (LineNumberTableOffset);
701 bw.Write (NumLexicalBlocks);
702 bw.Write (LexicalBlockTableOffset);
703 bw.Write (NamespaceID);
705 return new MethodSourceEntry (index, file_offset, StartRow, EndRow);
708 internal void WriteIndex (BinaryWriter bw)
710 index_entry.Write (bw);
713 public override string ToString ()
715 return String.Format ("[Method {0}:{1}:{2}:{3}:{4} - {7}:{8}:{9}:{10} - {5} - {6}]",
716 index, Token, SourceFileIndex, StartRow, EndRow,
717 SourceFile, FullName, ClassTypeIndex, NumParameters,
718 NumLocals, NumLineNumbers);
722 public struct NamespaceEntry
724 public readonly string Name;
725 public readonly int Index;
726 public readonly int Parent;
727 public readonly string[] UsingClauses;
729 public NamespaceEntry (string name, int index, string[] using_clauses, int parent)
733 this.Parent = parent;
734 this.UsingClauses = using_clauses != null ? using_clauses : new string [0];
737 internal void Write (MonoSymbolFile file, BinaryWriter bw)
739 file.WriteString (bw, Name);
742 bw.Write (UsingClauses.Length);
743 foreach (string uc in UsingClauses)
744 file.WriteString (bw, uc);
747 public override string ToString ()
749 return String.Format ("[Namespace {0}:{1}:{2}]", Name, Index, Parent);