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 = 31;
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 internal 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
334 internal void Write (BinaryWriter bw)
337 bw.Write (FileOffset);
342 public int CompareTo (object obj)
344 MethodSourceEntry method = (MethodSourceEntry) obj;
346 if (method.StartRow < StartRow)
348 else if (method.StartRow > StartRow)
354 public override string ToString ()
356 return String.Format ("MethodSourceEntry ({0}:{1}:{2}:{3})",
357 Index, FileOffset, StartRow, EndRow);
361 public class MethodEntry
363 #region This is actually written to the symbol file
364 public readonly int SourceFileIndex;
365 public readonly int Token;
366 public readonly int StartRow;
367 public readonly int EndRow;
368 public readonly int ClassTypeIndex;
369 public readonly int NumParameters;
370 public readonly int NumLocals;
371 public readonly int NumLineNumbers;
372 public readonly int NamespaceID;
376 int TypeIndexTableOffset;
377 int LocalVariableTableOffset;
378 int LineNumberTableOffset;
386 public readonly SourceFileEntry SourceFile;
387 public readonly LineNumberEntry[] LineNumbers;
388 public readonly int[] ParamTypeIndices;
389 public readonly int[] LocalTypeIndices;
390 public readonly LocalVariableEntry[] Locals;
392 public static int Size
403 public string FullName {
404 get { return full_name; }
407 internal MethodEntry (MonoSymbolFile file, BinaryReader reader, int index)
410 SourceFileIndex = reader.ReadInt32 ();
411 Token = reader.ReadInt32 ();
412 StartRow = reader.ReadInt32 ();
413 EndRow = reader.ReadInt32 ();
414 ClassTypeIndex = reader.ReadInt32 ();
415 NumParameters = reader.ReadInt32 ();
416 NumLocals = reader.ReadInt32 ();
417 NumLineNumbers = reader.ReadInt32 ();
418 NameOffset = reader.ReadInt32 ();
419 FullNameOffset = reader.ReadInt32 ();
420 TypeIndexTableOffset = reader.ReadInt32 ();
421 LocalVariableTableOffset = reader.ReadInt32 ();
422 LineNumberTableOffset = reader.ReadInt32 ();
423 NamespaceID = reader.ReadInt32 ();
425 name = file.ReadString (NameOffset);
426 full_name = file.ReadString (FullNameOffset);
428 SourceFile = file.GetSourceFile (SourceFileIndex);
430 if (LineNumberTableOffset != 0) {
431 long old_pos = reader.BaseStream.Position;
432 reader.BaseStream.Position = LineNumberTableOffset;
434 LineNumbers = new LineNumberEntry [NumLineNumbers];
436 for (int i = 0; i < NumLineNumbers; i++)
437 LineNumbers [i] = new LineNumberEntry (reader);
439 reader.BaseStream.Position = old_pos;
442 if (LocalVariableTableOffset != 0) {
443 long old_pos = reader.BaseStream.Position;
444 reader.BaseStream.Position = LocalVariableTableOffset;
446 Locals = new LocalVariableEntry [NumLocals];
448 for (int i = 0; i < NumLocals; i++)
449 Locals [i] = new LocalVariableEntry (reader);
451 reader.BaseStream.Position = old_pos;
454 if (TypeIndexTableOffset != 0) {
455 long old_pos = reader.BaseStream.Position;
456 reader.BaseStream.Position = TypeIndexTableOffset;
458 ParamTypeIndices = new int [NumParameters];
459 LocalTypeIndices = new int [NumLocals];
461 for (int i = 0; i < NumParameters; i++)
462 ParamTypeIndices [i] = reader.ReadInt32 ();
463 for (int i = 0; i < NumLocals; i++)
464 LocalTypeIndices [i] = reader.ReadInt32 ();
466 reader.BaseStream.Position = old_pos;
470 internal MethodEntry (MonoSymbolFile file, SourceFileEntry source, MethodBase method,
471 int token, LocalVariableEntry[] locals, LineNumberEntry[] lines,
472 int start_row, int end_row, int namespace_id)
474 index = file.GetNextMethodIndex ();
477 SourceFileIndex = source.Index;
479 StartRow = start_row;
481 NamespaceID = namespace_id;
483 LineNumbers = BuildLineNumberTable (lines);
484 NumLineNumbers = LineNumbers.Length;
486 ParameterInfo[] parameters = method.GetParameters ();
487 if (parameters == null)
488 parameters = new ParameterInfo [0];
490 StringBuilder sb = new StringBuilder ();
491 sb.Append (method.DeclaringType.FullName);
493 sb.Append (method.Name);
495 for (int i = 0; i < parameters.Length; i++) {
498 sb.Append (parameters [i].ParameterType.FullName);
503 full_name = sb.ToString ();
505 NumParameters = parameters.Length;
506 ParamTypeIndices = new int [NumParameters];
507 for (int i = 0; i < NumParameters; i++)
508 ParamTypeIndices [i] = file.DefineType (parameters [i].ParameterType);
510 NumLocals = locals.Length;
513 LocalTypeIndices = new int [NumLocals];
514 for (int i = 0; i < NumLocals; i++)
515 LocalTypeIndices [i] = file.GetNextTypeIndex ();
517 ClassTypeIndex = file.DefineType (method.ReflectedType);
520 LineNumberEntry[] BuildLineNumberTable (LineNumberEntry[] line_numbers)
522 ArrayList list = new ArrayList ();
523 int last_offset = -1;
526 for (int i = 0; i < line_numbers.Length; i++) {
527 LineNumberEntry line = (LineNumberEntry) line_numbers [i];
529 if (line.Offset > last_offset) {
531 list.Add (new LineNumberEntry (last_row, last_offset));
533 last_offset = line.Offset;
534 } else if (line.Row > last_row) {
540 list.Add (new LineNumberEntry (last_row, last_offset));
542 LineNumberEntry[] retval = new LineNumberEntry [list.Count];
543 list.CopyTo (retval, 0);
547 internal MethodSourceEntry Write (MonoSymbolFile file, BinaryWriter bw)
549 NameOffset = (int) bw.BaseStream.Position;
550 file.WriteString (bw, name);
552 FullNameOffset = (int) bw.BaseStream.Position;
553 file.WriteString (bw, full_name);
555 TypeIndexTableOffset = (int) bw.BaseStream.Position;
557 for (int i = 0; i < NumParameters; i++)
558 bw.Write (ParamTypeIndices [i]);
559 for (int i = 0; i < NumLocals; i++)
560 bw.Write (LocalTypeIndices [i]);
562 LocalVariableTableOffset = (int) bw.BaseStream.Position;
564 for (int i = 0; i < NumLocals; i++)
565 Locals [i].Write (file, bw);
567 LineNumberTableOffset = (int) bw.BaseStream.Position;
569 for (int i = 0; i < NumLineNumbers; i++)
570 LineNumbers [i].Write (bw);
572 file.LineNumberCount += NumLineNumbers;
573 file.LocalCount += NumLocals;
575 file_offset = (int) bw.BaseStream.Position;
577 bw.Write (SourceFileIndex);
581 bw.Write (ClassTypeIndex);
582 bw.Write (NumParameters);
583 bw.Write (NumLocals);
584 bw.Write (NumLineNumbers);
585 bw.Write (NameOffset);
586 bw.Write (FullNameOffset);
587 bw.Write (TypeIndexTableOffset);
588 bw.Write (LocalVariableTableOffset);
589 bw.Write (LineNumberTableOffset);
590 bw.Write (NamespaceID);
592 return new MethodSourceEntry (index, file_offset, StartRow, EndRow);
595 internal void WriteIndex (BinaryWriter bw)
597 bw.Write (file_offset);
598 bw.Write (FullNameOffset);
601 public override string ToString ()
603 return String.Format ("[Method {0}:{1}:{2}:{3}:{4} - {7}:{8}:{9}:{10} - {5} - {6}]",
604 index, Token, SourceFileIndex, StartRow, EndRow,
605 SourceFile, FullName, ClassTypeIndex, NumParameters,
606 NumLocals, NumLineNumbers);
610 public struct NamespaceEntry
612 public readonly string Name;
613 public readonly int Index;
614 public readonly int Parent;
615 public readonly string[] UsingClauses;
617 public NamespaceEntry (string name, int index, string[] using_clauses, int parent)
621 this.Parent = parent;
622 this.UsingClauses = using_clauses != null ? using_clauses : new string [0];
625 internal void Write (MonoSymbolFile file, BinaryWriter bw)
627 file.WriteString (bw, Name);
630 bw.Write (UsingClauses.Length);
631 foreach (string uc in UsingClauses)
632 file.WriteString (bw, uc);
635 public override string ToString ()
637 return String.Format ("[Namespace {0}:{1}:{2}]", Name, Index, Parent);