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 = 32;
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 struct LocalVariableEntry
141 public readonly string Name;
142 public readonly FieldAttributes Attributes;
143 public readonly byte[] Signature;
145 public LocalVariableEntry (string Name, FieldAttributes Attributes, byte[] Signature)
148 this.Attributes = Attributes;
149 this.Signature = Signature;
152 internal LocalVariableEntry (BinaryReader reader)
154 int name_length = reader.ReadInt32 ();
155 byte[] name = reader.ReadBytes (name_length);
156 Name = Encoding.UTF8.GetString (name);
157 Attributes = (FieldAttributes) reader.ReadInt32 ();
158 int sig_length = reader.ReadInt32 ();
159 Signature = reader.ReadBytes (sig_length);
162 internal void Write (MonoSymbolFile file, BinaryWriter bw)
164 file.WriteString (bw, Name);
165 bw.Write ((int) Attributes);
166 bw.Write ((int) Signature.Length);
167 bw.Write (Signature);
170 public override string ToString ()
172 return String.Format ("[LocalVariable {0}:{1}]", Name, Attributes);
176 public class SourceFileEntry
181 ArrayList namespaces;
182 int index, count, name_offset, method_offset;
183 int namespace_count, nstable_offset;
186 public static int Size {
190 internal SourceFileEntry (MonoSymbolFile file, string file_name)
193 this.file_name = file_name;
194 this.index = file.AddSource (this);
197 methods = new ArrayList ();
198 namespaces = new ArrayList ();
201 public void DefineMethod (MethodBase method, int token, LocalVariableEntry[] locals,
202 LineNumberEntry[] lines, int start, int end, int namespace_id)
205 throw new InvalidOperationException ();
207 MethodEntry entry = new MethodEntry (
208 file, this, method, token, locals, lines, start, end, namespace_id);
211 file.AddMethod (entry);
214 public int DefineNamespace (string name, string[] using_clauses, int parent)
217 throw new InvalidOperationException ();
219 int index = file.GetNextNamespaceIndex ();
220 NamespaceEntry ns = new NamespaceEntry (name, index, using_clauses, parent);
225 internal void WriteData (BinaryWriter bw)
227 name_offset = (int) bw.BaseStream.Position;
228 file.WriteString (bw, file_name);
230 ArrayList list = new ArrayList ();
231 foreach (MethodEntry entry in methods)
232 list.Add (entry.Write (file, bw));
236 method_offset = (int) bw.BaseStream.Position;
237 foreach (MethodSourceEntry method in list)
240 namespace_count = namespaces.Count;
241 nstable_offset = (int) bw.BaseStream.Position;
242 foreach (NamespaceEntry ns in namespaces)
246 internal void Write (BinaryWriter bw)
250 bw.Write (namespace_count);
251 bw.Write (name_offset);
252 bw.Write (method_offset);
253 bw.Write (nstable_offset);
256 internal SourceFileEntry (MonoSymbolFile file, BinaryReader reader)
260 index = reader.ReadInt32 ();
261 count = reader.ReadInt32 ();
262 namespace_count = reader.ReadInt32 ();
263 name_offset = reader.ReadInt32 ();
264 method_offset = reader.ReadInt32 ();
265 nstable_offset = reader.ReadInt32 ();
267 file_name = file.ReadString (name_offset);
271 get { return index; }
274 public string FileName {
275 get { return file_name; }
278 public MethodSourceEntry[] Methods {
281 throw new InvalidOperationException ();
283 BinaryReader reader = file.BinaryReader;
284 int old_pos = (int) reader.BaseStream.Position;
286 reader.BaseStream.Position = method_offset;
287 ArrayList list = new ArrayList ();
288 for (int i = 0; i < count; i ++)
289 list.Add (new MethodSourceEntry (reader));
290 reader.BaseStream.Position = old_pos;
292 MethodSourceEntry[] retval = new MethodSourceEntry [count];
293 list.CopyTo (retval, 0);
298 public override string ToString ()
300 return String.Format ("SourceFileEntry ({0}:{1}:{2})", index, file_name, count);
304 public struct MethodSourceEntry : IComparable
306 public readonly int Index;
307 public readonly int FileOffset;
308 public readonly int StartRow;
309 public readonly int EndRow;
311 public MethodSourceEntry (int index, int file_offset, int start, int end)
314 this.FileOffset = file_offset;
315 this.StartRow = start;
319 internal MethodSourceEntry (BinaryReader reader)
321 Index = reader.ReadInt32 ();
322 FileOffset = reader.ReadInt32 ();
323 StartRow = reader.ReadInt32 ();
324 EndRow = reader.ReadInt32 ();
327 public static int Size {
331 internal void Write (BinaryWriter bw)
334 bw.Write (FileOffset);
339 public int CompareTo (object obj)
341 MethodSourceEntry method = (MethodSourceEntry) obj;
343 if (method.StartRow < StartRow)
345 else if (method.StartRow > StartRow)
351 public override string ToString ()
353 return String.Format ("MethodSourceEntry ({0}:{1}:{2}:{3})",
354 Index, FileOffset, StartRow, EndRow);
358 public struct MethodIndexEntry
360 public readonly int FileOffset;
361 public readonly int FullNameOffset;
362 public readonly int Token;
364 public static int Size {
368 public MethodIndexEntry (int offset, int name_offset, int token)
370 this.FileOffset = offset;
371 this.FullNameOffset = name_offset;
375 internal MethodIndexEntry (BinaryReader reader)
377 FileOffset = reader.ReadInt32 ();
378 FullNameOffset = reader.ReadInt32 ();
379 Token = reader.ReadInt32 ();
382 internal void Write (BinaryWriter bw)
384 bw.Write (FileOffset);
385 bw.Write (FullNameOffset);
389 public override string ToString ()
391 return String.Format ("MethodIndexEntry ({0}:{1}:{2:x})",
392 FileOffset, FullNameOffset, Token);
396 public class MethodEntry
398 #region This is actually written to the symbol file
399 public readonly int SourceFileIndex;
400 public readonly int Token;
401 public readonly int StartRow;
402 public readonly int EndRow;
403 public readonly int ClassTypeIndex;
404 public readonly int NumParameters;
405 public readonly int NumLocals;
406 public readonly int NumLineNumbers;
407 public readonly int NamespaceID;
411 int TypeIndexTableOffset;
412 int LocalVariableTableOffset;
413 int LineNumberTableOffset;
420 MethodIndexEntry index_entry;
422 public readonly SourceFileEntry SourceFile;
423 public readonly LineNumberEntry[] LineNumbers;
424 public readonly int[] ParamTypeIndices;
425 public readonly int[] LocalTypeIndices;
426 public readonly LocalVariableEntry[] Locals;
427 public readonly Type[] LocalTypes;
429 public readonly MonoSymbolFile SymbolFile;
431 public static int Size {
439 public string FullName {
440 get { return full_name; }
443 public MethodBase MethodBase {
444 get { return SymbolFile.Assembly.MonoDebugger_GetMethod (Token); }
447 internal MethodEntry (MonoSymbolFile file, BinaryReader reader, int index)
449 this.SymbolFile = file;
451 SourceFileIndex = reader.ReadInt32 ();
452 Token = reader.ReadInt32 ();
453 StartRow = reader.ReadInt32 ();
454 EndRow = reader.ReadInt32 ();
455 ClassTypeIndex = reader.ReadInt32 ();
456 NumParameters = reader.ReadInt32 ();
457 NumLocals = reader.ReadInt32 ();
458 NumLineNumbers = reader.ReadInt32 ();
459 NameOffset = reader.ReadInt32 ();
460 FullNameOffset = reader.ReadInt32 ();
461 TypeIndexTableOffset = reader.ReadInt32 ();
462 LocalVariableTableOffset = reader.ReadInt32 ();
463 LineNumberTableOffset = reader.ReadInt32 ();
464 NamespaceID = reader.ReadInt32 ();
466 name = file.ReadString (NameOffset);
467 full_name = file.ReadString (FullNameOffset);
469 SourceFile = file.GetSourceFile (SourceFileIndex);
471 if (LineNumberTableOffset != 0) {
472 long old_pos = reader.BaseStream.Position;
473 reader.BaseStream.Position = LineNumberTableOffset;
475 LineNumbers = new LineNumberEntry [NumLineNumbers];
477 for (int i = 0; i < NumLineNumbers; i++)
478 LineNumbers [i] = new LineNumberEntry (reader);
480 reader.BaseStream.Position = old_pos;
483 if (LocalVariableTableOffset != 0) {
484 long old_pos = reader.BaseStream.Position;
485 reader.BaseStream.Position = LocalVariableTableOffset;
487 Locals = new LocalVariableEntry [NumLocals];
488 LocalTypes = new Type [NumLocals];
490 Assembly ass = file.Assembly;
492 for (int i = 0; i < NumLocals; i++) {
493 Locals [i] = new LocalVariableEntry (reader);
494 LocalTypes [i] = ass.MonoDebugger_GetLocalTypeFromSignature (
495 Locals [i].Signature);
498 reader.BaseStream.Position = old_pos;
501 if (TypeIndexTableOffset != 0) {
502 long old_pos = reader.BaseStream.Position;
503 reader.BaseStream.Position = TypeIndexTableOffset;
505 ParamTypeIndices = new int [NumParameters];
506 LocalTypeIndices = new int [NumLocals];
508 for (int i = 0; i < NumParameters; i++)
509 ParamTypeIndices [i] = reader.ReadInt32 ();
510 for (int i = 0; i < NumLocals; i++)
511 LocalTypeIndices [i] = reader.ReadInt32 ();
513 reader.BaseStream.Position = old_pos;
517 internal MethodEntry (MonoSymbolFile file, SourceFileEntry source, MethodBase method,
518 int token, LocalVariableEntry[] locals, LineNumberEntry[] lines,
519 int start_row, int end_row, int namespace_id)
521 this.SymbolFile = file;
522 index = file.GetNextMethodIndex ();
525 SourceFileIndex = source.Index;
527 StartRow = start_row;
529 NamespaceID = namespace_id;
531 LineNumbers = BuildLineNumberTable (lines);
532 NumLineNumbers = LineNumbers.Length;
534 ParameterInfo[] parameters = method.GetParameters ();
535 if (parameters == null)
536 parameters = new ParameterInfo [0];
538 StringBuilder sb = new StringBuilder ();
539 sb.Append (method.DeclaringType.FullName);
541 sb.Append (method.Name);
543 for (int i = 0; i < parameters.Length; i++) {
546 sb.Append (parameters [i].ParameterType.FullName);
551 full_name = sb.ToString ();
553 NumParameters = parameters.Length;
554 ParamTypeIndices = new int [NumParameters];
555 for (int i = 0; i < NumParameters; i++)
556 ParamTypeIndices [i] = file.DefineType (parameters [i].ParameterType);
558 NumLocals = locals.Length;
561 LocalTypeIndices = new int [NumLocals];
562 for (int i = 0; i < NumLocals; i++)
563 LocalTypeIndices [i] = file.GetNextTypeIndex ();
565 ClassTypeIndex = file.DefineType (method.ReflectedType);
568 LineNumberEntry[] BuildLineNumberTable (LineNumberEntry[] line_numbers)
570 ArrayList list = new ArrayList ();
571 int last_offset = -1;
574 for (int i = 0; i < line_numbers.Length; i++) {
575 LineNumberEntry line = (LineNumberEntry) line_numbers [i];
577 if (line.Offset > last_offset) {
579 list.Add (new LineNumberEntry (last_row, last_offset));
581 last_offset = line.Offset;
582 } else if (line.Row > last_row) {
588 list.Add (new LineNumberEntry (last_row, last_offset));
590 LineNumberEntry[] retval = new LineNumberEntry [list.Count];
591 list.CopyTo (retval, 0);
595 internal MethodSourceEntry Write (MonoSymbolFile file, BinaryWriter bw)
597 NameOffset = (int) bw.BaseStream.Position;
598 file.WriteString (bw, name);
600 FullNameOffset = (int) bw.BaseStream.Position;
601 file.WriteString (bw, full_name);
603 TypeIndexTableOffset = (int) bw.BaseStream.Position;
605 for (int i = 0; i < NumParameters; i++)
606 bw.Write (ParamTypeIndices [i]);
607 for (int i = 0; i < NumLocals; i++)
608 bw.Write (LocalTypeIndices [i]);
610 LocalVariableTableOffset = (int) bw.BaseStream.Position;
612 for (int i = 0; i < NumLocals; i++)
613 Locals [i].Write (file, bw);
615 LineNumberTableOffset = (int) bw.BaseStream.Position;
617 for (int i = 0; i < NumLineNumbers; i++)
618 LineNumbers [i].Write (bw);
620 file.LineNumberCount += NumLineNumbers;
621 file.LocalCount += NumLocals;
623 file_offset = (int) bw.BaseStream.Position;
625 index_entry = new MethodIndexEntry (file_offset, FullNameOffset, Token);
627 bw.Write (SourceFileIndex);
631 bw.Write (ClassTypeIndex);
632 bw.Write (NumParameters);
633 bw.Write (NumLocals);
634 bw.Write (NumLineNumbers);
635 bw.Write (NameOffset);
636 bw.Write (FullNameOffset);
637 bw.Write (TypeIndexTableOffset);
638 bw.Write (LocalVariableTableOffset);
639 bw.Write (LineNumberTableOffset);
640 bw.Write (NamespaceID);
642 return new MethodSourceEntry (index, file_offset, StartRow, EndRow);
645 internal void WriteIndex (BinaryWriter bw)
647 index_entry.Write (bw);
650 public override string ToString ()
652 return String.Format ("[Method {0}:{1}:{2}:{3}:{4} - {7}:{8}:{9}:{10} - {5} - {6}]",
653 index, Token, SourceFileIndex, StartRow, EndRow,
654 SourceFile, FullName, ClassTypeIndex, NumParameters,
655 NumLocals, NumLineNumbers);
659 public struct NamespaceEntry
661 public readonly string Name;
662 public readonly int Index;
663 public readonly int Parent;
664 public readonly string[] UsingClauses;
666 public NamespaceEntry (string name, int index, string[] using_clauses, int parent)
670 this.Parent = parent;
671 this.UsingClauses = using_clauses != null ? using_clauses : new string [0];
674 internal void Write (MonoSymbolFile file, BinaryWriter bw)
676 file.WriteString (bw, Name);
679 bw.Write (UsingClauses.Length);
680 foreach (string uc in UsingClauses)
681 file.WriteString (bw, uc);
684 public override string ToString ()
686 return String.Format ("[Namespace {0}:{1}:{2}]", Name, Index, Parent);