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 = 29;
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 int index, count, name_offset, method_offset;
184 internal static int Size {
188 internal SourceFileEntry (MonoSymbolFile file, string file_name, int index)
191 this.file_name = file_name;
195 methods = new ArrayList ();
198 public void DefineMethod (MethodBase method, int token, LocalVariableEntry[] locals,
199 LineNumberEntry[] lines, int start, int end)
202 throw new InvalidOperationException ();
204 MethodEntry entry = new MethodEntry (
205 file, this, method, token, locals, lines, start, end);
208 file.AddMethod (entry);
211 internal void WriteData (BinaryWriter bw)
213 name_offset = (int) bw.BaseStream.Position;
214 file.WriteString (bw, file_name);
216 ArrayList list = new ArrayList ();
217 foreach (MethodEntry entry in methods)
218 list.Add (entry.Write (file, bw));
222 method_offset = (int) bw.BaseStream.Position;
223 foreach (MethodSourceEntry method in list)
227 internal void Write (BinaryWriter bw)
231 bw.Write (name_offset);
232 bw.Write (method_offset);
235 internal SourceFileEntry (MonoSymbolFile file, BinaryReader reader)
239 index = reader.ReadInt32 ();
240 count = reader.ReadInt32 ();
241 name_offset = reader.ReadInt32 ();
242 method_offset = reader.ReadInt32 ();
244 file_name = file.ReadString (name_offset);
248 get { return index; }
251 public string FileName {
252 get { return file_name; }
255 public MethodSourceEntry[] Methods {
258 throw new InvalidOperationException ();
260 BinaryReader reader = file.BinaryReader;
261 int old_pos = (int) reader.BaseStream.Position;
263 reader.BaseStream.Position = method_offset;
264 ArrayList list = new ArrayList ();
265 for (int i = 0; i < count; i ++)
266 list.Add (new MethodSourceEntry (reader));
267 reader.BaseStream.Position = old_pos;
269 MethodSourceEntry[] retval = new MethodSourceEntry [count];
270 list.CopyTo (retval, 0);
275 public override string ToString ()
277 return String.Format ("SourceFileEntry ({0}:{1}:{2})", index, file_name, count);
281 public struct MethodSourceEntry : IComparable
283 public readonly int Index;
284 public readonly int FileOffset;
285 public readonly int StartRow;
286 public readonly int EndRow;
288 public MethodSourceEntry (int index, int file_offset, int start, int end)
291 this.FileOffset = file_offset;
292 this.StartRow = start;
296 internal MethodSourceEntry (BinaryReader reader)
298 Index = reader.ReadInt32 ();
299 FileOffset = reader.ReadInt32 ();
300 StartRow = reader.ReadInt32 ();
301 EndRow = reader.ReadInt32 ();
304 public static int Size
311 internal void Write (BinaryWriter bw)
314 bw.Write (FileOffset);
319 public int CompareTo (object obj)
321 MethodSourceEntry method = (MethodSourceEntry) obj;
323 if (method.StartRow < StartRow)
325 else if (method.StartRow > StartRow)
331 public override string ToString ()
333 return String.Format ("MethodSourceEntry ({0}:{1}:{2}:{3})",
334 Index, FileOffset, StartRow, EndRow);
338 public class MethodEntry
340 #region This is actually written to the symbol file
341 public readonly int SourceFileIndex;
342 public readonly int Token;
343 public readonly int StartRow;
344 public readonly int EndRow;
345 public readonly int ThisTypeIndex;
346 public readonly int NumParameters;
347 public readonly int NumLocals;
348 public readonly int NumLineNumbers;
352 int TypeIndexTableOffset;
353 int LocalVariableTableOffset;
354 int LineNumberTableOffset;
362 public readonly SourceFileEntry SourceFile;
363 public readonly LineNumberEntry[] LineNumbers;
364 public readonly int[] ParamTypeIndices;
365 public readonly int[] LocalTypeIndices;
366 public readonly LocalVariableEntry[] Locals;
368 public static int Size
379 public string FullName {
380 get { return full_name; }
383 internal MethodEntry (MonoSymbolFile file, BinaryReader reader, int index)
386 SourceFileIndex = reader.ReadInt32 ();
387 Token = reader.ReadInt32 ();
388 StartRow = reader.ReadInt32 ();
389 EndRow = reader.ReadInt32 ();
390 ThisTypeIndex = reader.ReadInt32 ();
391 NumParameters = reader.ReadInt32 ();
392 NumLocals = reader.ReadInt32 ();
393 NumLineNumbers = reader.ReadInt32 ();
394 NameOffset = reader.ReadInt32 ();
395 FullNameOffset = reader.ReadInt32 ();
396 TypeIndexTableOffset = reader.ReadInt32 ();
397 LocalVariableTableOffset = reader.ReadInt32 ();
398 LineNumberTableOffset = reader.ReadInt32 ();
400 name = file.ReadString (NameOffset);
401 full_name = file.ReadString (FullNameOffset);
403 SourceFile = file.GetSourceFile (SourceFileIndex);
405 if (LineNumberTableOffset != 0) {
406 long old_pos = reader.BaseStream.Position;
407 reader.BaseStream.Position = LineNumberTableOffset;
409 LineNumbers = new LineNumberEntry [NumLineNumbers];
411 for (int i = 0; i < NumLineNumbers; i++)
412 LineNumbers [i] = new LineNumberEntry (reader);
414 reader.BaseStream.Position = old_pos;
417 if (LocalVariableTableOffset != 0) {
418 long old_pos = reader.BaseStream.Position;
419 reader.BaseStream.Position = LocalVariableTableOffset;
421 Locals = new LocalVariableEntry [NumLocals];
423 for (int i = 0; i < NumLocals; i++)
424 Locals [i] = new LocalVariableEntry (reader);
426 reader.BaseStream.Position = old_pos;
429 if (TypeIndexTableOffset != 0) {
430 long old_pos = reader.BaseStream.Position;
431 reader.BaseStream.Position = TypeIndexTableOffset;
433 ParamTypeIndices = new int [NumParameters];
434 LocalTypeIndices = new int [NumLocals];
436 for (int i = 0; i < NumParameters; i++)
437 ParamTypeIndices [i] = reader.ReadInt32 ();
438 for (int i = 0; i < NumLocals; i++)
439 LocalTypeIndices [i] = reader.ReadInt32 ();
441 reader.BaseStream.Position = old_pos;
445 internal MethodEntry (MonoSymbolFile file, SourceFileEntry source, MethodBase method,
446 int token, LocalVariableEntry[] locals, LineNumberEntry[] lines,
447 int start_row, int end_row)
449 index = file.GetNextMethodIndex ();
452 SourceFileIndex = source.Index;
454 StartRow = start_row;
457 LineNumbers = BuildLineNumberTable (lines);
458 NumLineNumbers = LineNumbers.Length;
460 ParameterInfo[] parameters = method.GetParameters ();
461 if (parameters == null)
462 parameters = new ParameterInfo [0];
464 StringBuilder sb = new StringBuilder ();
465 sb.Append (method.DeclaringType.FullName);
467 sb.Append (method.Name);
469 for (int i = 0; i < parameters.Length; i++) {
472 sb.Append (parameters [i].ParameterType.FullName);
477 full_name = sb.ToString ();
479 NumParameters = parameters.Length;
480 ParamTypeIndices = new int [NumParameters];
481 for (int i = 0; i < NumParameters; i++)
482 ParamTypeIndices [i] = file.DefineType (parameters [i].ParameterType);
484 NumLocals = locals.Length;
487 LocalTypeIndices = new int [NumLocals];
488 for (int i = 0; i < NumLocals; i++)
489 LocalTypeIndices [i] = file.GetNextTypeIndex ();
494 ThisTypeIndex = file.DefineType (method.ReflectedType);
497 LineNumberEntry[] BuildLineNumberTable (LineNumberEntry[] line_numbers)
499 Array.Sort (line_numbers, LineNumberEntry.OffsetComparer);
501 ArrayList list = new ArrayList ();
502 int last_offset = -1;
505 for (int i = 0; i < line_numbers.Length; i++) {
506 LineNumberEntry line = (LineNumberEntry) line_numbers [i];
508 if (line.Offset > last_offset) {
510 list.Add (new LineNumberEntry (last_row, last_offset));
512 last_offset = line.Offset;
513 } else if (line.Row > last_row) {
519 list.Add (new LineNumberEntry (last_row, last_offset));
521 LineNumberEntry[] retval = new LineNumberEntry [list.Count];
522 list.CopyTo (retval, 0);
526 internal MethodSourceEntry Write (MonoSymbolFile file, BinaryWriter bw)
528 NameOffset = (int) bw.BaseStream.Position;
529 file.WriteString (bw, name);
531 FullNameOffset = (int) bw.BaseStream.Position;
532 file.WriteString (bw, full_name);
534 TypeIndexTableOffset = (int) bw.BaseStream.Position;
536 for (int i = 0; i < NumParameters; i++)
537 bw.Write (ParamTypeIndices [i]);
538 for (int i = 0; i < NumLocals; i++)
539 bw.Write (LocalTypeIndices [i]);
541 LocalVariableTableOffset = (int) bw.BaseStream.Position;
543 for (int i = 0; i < NumLocals; i++)
544 Locals [i].Write (file, bw);
546 LineNumberTableOffset = (int) bw.BaseStream.Position;
548 for (int i = 0; i < NumLineNumbers; i++)
549 LineNumbers [i].Write (bw);
551 file.LineNumberCount += NumLineNumbers;
552 file.LocalCount += NumLocals;
554 file_offset = (int) bw.BaseStream.Position;
556 bw.Write (SourceFileIndex);
560 bw.Write (ThisTypeIndex);
561 bw.Write (NumParameters);
562 bw.Write (NumLocals);
563 bw.Write (NumLineNumbers);
564 bw.Write (NameOffset);
565 bw.Write (FullNameOffset);
566 bw.Write (TypeIndexTableOffset);
567 bw.Write (LocalVariableTableOffset);
568 bw.Write (LineNumberTableOffset);
570 return new MethodSourceEntry (index, file_offset, StartRow, EndRow);
573 internal void WriteIndex (BinaryWriter bw)
575 bw.Write (file_offset);
576 bw.Write (FullNameOffset);
579 public override string ToString ()
581 return String.Format ("[Method {0}:{1}:{2}:{3}:{4} - {7}:{8}:{9}:{10} - {5} - {6}]",
582 index, Token, SourceFileIndex, StartRow, EndRow,
583 SourceFile, FullName, ThisTypeIndex, NumParameters,
584 NumLocals, NumLineNumbers);