//
using System;
-using System.Collections;
+using System.Security.Cryptography;
+using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Mono.CompilerServices.SymbolWriter
{
- public struct OffsetTable
+ public class OffsetTable
{
- public const int Version = 39;
- public const long Magic = 0x45e82623fd7fa614;
+ public const int MajorVersion = 50;
+ public const int MinorVersion = 0;
+ public const long Magic = 0x45e82623fd7fa614;
#region This is actually written to the symbol file
public int TotalFileSize;
public int DataSectionOffset;
public int DataSectionSize;
+ public int CompileUnitCount;
+ public int CompileUnitTableOffset;
+ public int CompileUnitTableSize;
public int SourceCount;
public int SourceTableOffset;
public int SourceTableSize;
public int MethodTableOffset;
public int MethodTableSize;
public int TypeCount;
+ public int AnonymousScopeCount;
+ public int AnonymousScopeTableOffset;
+ public int AnonymousScopeTableSize;
+
+ [Flags]
+ public enum Flags
+ {
+ IsAspxSource = 1,
+ WindowsFileNames = 2
+ }
+
+ public Flags FileFlags;
+
+ public int LineNumberTable_LineBase = LineNumberTable.Default_LineBase;
+ public int LineNumberTable_LineRange = LineNumberTable.Default_LineRange;
+ public int LineNumberTable_OpcodeBase = LineNumberTable.Default_OpcodeBase;
#endregion
- internal OffsetTable (BinaryReader reader)
+ internal OffsetTable ()
+ {
+ int platform = (int) Environment.OSVersion.Platform;
+ if ((platform != 4) && (platform != 128))
+ FileFlags |= Flags.WindowsFileNames;
+ }
+
+ internal OffsetTable (BinaryReader reader, int major_version, int minor_version)
{
TotalFileSize = reader.ReadInt32 ();
DataSectionOffset = reader.ReadInt32 ();
DataSectionSize = reader.ReadInt32 ();
+ CompileUnitCount = reader.ReadInt32 ();
+ CompileUnitTableOffset = reader.ReadInt32 ();
+ CompileUnitTableSize = reader.ReadInt32 ();
SourceCount = reader.ReadInt32 ();
SourceTableOffset = reader.ReadInt32 ();
SourceTableSize = reader.ReadInt32 ();
MethodTableOffset = reader.ReadInt32 ();
MethodTableSize = reader.ReadInt32 ();
TypeCount = reader.ReadInt32 ();
+
+ AnonymousScopeCount = reader.ReadInt32 ();
+ AnonymousScopeTableOffset = reader.ReadInt32 ();
+ AnonymousScopeTableSize = reader.ReadInt32 ();
+
+ LineNumberTable_LineBase = reader.ReadInt32 ();
+ LineNumberTable_LineRange = reader.ReadInt32 ();
+ LineNumberTable_OpcodeBase = reader.ReadInt32 ();
+
+ FileFlags = (Flags) reader.ReadInt32 ();
}
- internal void Write (BinaryWriter bw)
+ internal void Write (BinaryWriter bw, int major_version, int minor_version)
{
bw.Write (TotalFileSize);
bw.Write (DataSectionOffset);
bw.Write (DataSectionSize);
+ bw.Write (CompileUnitCount);
+ bw.Write (CompileUnitTableOffset);
+ bw.Write (CompileUnitTableSize);
bw.Write (SourceCount);
bw.Write (SourceTableOffset);
bw.Write (SourceTableSize);
bw.Write (MethodTableOffset);
bw.Write (MethodTableSize);
bw.Write (TypeCount);
+
+ bw.Write (AnonymousScopeCount);
+ bw.Write (AnonymousScopeTableOffset);
+ bw.Write (AnonymousScopeTableSize);
+
+ bw.Write (LineNumberTable_LineBase);
+ bw.Write (LineNumberTable_LineRange);
+ bw.Write (LineNumberTable_OpcodeBase);
+
+ bw.Write ((int) FileFlags);
}
public override string ToString ()
}
}
- public struct LineNumberEntry
+ public class LineNumberEntry
{
#region This is actually written to the symbol file
public readonly int Row;
+ public readonly int File;
public readonly int Offset;
+ public readonly bool IsHidden;
#endregion
- public LineNumberEntry (int row, int offset)
+ public LineNumberEntry (int file, int row, int offset)
+ : this (file, row, offset, false)
+ { }
+
+ public LineNumberEntry (int file, int row, int offset, bool is_hidden)
{
+ this.File = file;
this.Row = row;
this.Offset = offset;
+ this.IsHidden = is_hidden;
}
- public static LineNumberEntry Null = new LineNumberEntry (0, 0);
-
- internal LineNumberEntry (BinaryReader reader)
- {
- Row = reader.ReadInt32 ();
- Offset = reader.ReadInt32 ();
- }
-
- internal void Write (BinaryWriter bw)
- {
- bw.Write (Row);
- bw.Write (Offset);
- }
+ public static LineNumberEntry Null = new LineNumberEntry (0, 0, 0);
- private class OffsetComparerClass : IComparer
+ private class OffsetComparerClass : IComparer<LineNumberEntry>
{
- public int Compare (object a, object b)
+ public int Compare (LineNumberEntry l1, LineNumberEntry l2)
{
- LineNumberEntry l1 = (LineNumberEntry) a;
- LineNumberEntry l2 = (LineNumberEntry) b;
-
if (l1.Offset < l2.Offset)
return -1;
else if (l1.Offset > l2.Offset)
}
}
- private class RowComparerClass : IComparer
+ private class RowComparerClass : IComparer<LineNumberEntry>
{
- public int Compare (object a, object b)
+ public int Compare (LineNumberEntry l1, LineNumberEntry l2)
{
- LineNumberEntry l1 = (LineNumberEntry) a;
- LineNumberEntry l2 = (LineNumberEntry) b;
-
if (l1.Row < l2.Row)
return -1;
else if (l1.Row > l2.Row)
}
}
- public static readonly IComparer OffsetComparer = new OffsetComparerClass ();
- public static readonly IComparer RowComparer = new RowComparerClass ();
+ public static readonly IComparer<LineNumberEntry> OffsetComparer = new OffsetComparerClass ();
+ public static readonly IComparer<LineNumberEntry> RowComparer = new RowComparerClass ();
public override string ToString ()
{
- return String.Format ("[Line {0}:{1}]", Row, Offset);
+ return String.Format ("[Line {0}:{1}:{2}]", File, Row, Offset);
}
}
- public class LexicalBlockEntry
+ public class CodeBlockEntry
{
public int Index;
#region This is actually written to the symbol file
+ public int Parent;
+ public Type BlockType;
public int StartOffset;
public int EndOffset;
#endregion
- public LexicalBlockEntry (int index, int start_offset)
+ public enum Type {
+ Lexical = 1,
+ CompilerGenerated = 2,
+ IteratorBody = 3,
+ IteratorDispatcher = 4
+ }
+
+ public CodeBlockEntry (int index, int parent, Type type, int start_offset)
{
this.Index = index;
+ this.Parent = parent;
+ this.BlockType = type;
this.StartOffset = start_offset;
}
- internal LexicalBlockEntry (int index, MyBinaryReader reader)
+ internal CodeBlockEntry (int index, MyBinaryReader reader)
{
this.Index = index;
- this.StartOffset = reader.ReadInt32 ();
- this.EndOffset = reader.ReadInt32 ();
+ int type_flag = reader.ReadLeb128 ();
+ BlockType = (Type) (type_flag & 0x3f);
+ this.Parent = reader.ReadLeb128 ();
+ this.StartOffset = reader.ReadLeb128 ();
+ this.EndOffset = reader.ReadLeb128 ();
+
+ /* Reserved for future extensions. */
+ if ((type_flag & 0x40) != 0) {
+ int data_size = reader.ReadInt16 ();
+ reader.BaseStream.Position += data_size;
+ }
}
public void Close (int end_offset)
internal void Write (MyBinaryWriter bw)
{
- bw.Write (StartOffset);
- bw.Write (EndOffset);
+ bw.WriteLeb128 ((int) BlockType);
+ bw.WriteLeb128 (Parent);
+ bw.WriteLeb128 (StartOffset);
+ bw.WriteLeb128 (EndOffset);
}
public override string ToString ()
{
- return String.Format ("[LexicalBlock {0}:{1}]", StartOffset, EndOffset);
+ return String.Format ("[CodeBlock {0}:{1}:{2}:{3}:{4}]",
+ Index, Parent, BlockType, StartOffset, EndOffset);
}
}
#region This is actually written to the symbol file
public readonly int Index;
public readonly string Name;
- public readonly byte[] Signature;
public readonly int BlockIndex;
#endregion
- public LocalVariableEntry (int Index, string Name, byte[] Signature, int BlockIndex)
+ public LocalVariableEntry (int index, string name, int block)
{
- this.Index = Index;
- this.Name = Name;
- this.Signature = Signature;
- this.BlockIndex = BlockIndex;
+ this.Index = index;
+ this.Name = name;
+ this.BlockIndex = block;
}
- internal LocalVariableEntry (MyBinaryReader reader)
+ internal LocalVariableEntry (MonoSymbolFile file, MyBinaryReader reader)
{
Index = reader.ReadLeb128 ();
Name = reader.ReadString ();
- int sig_length = reader.ReadLeb128 ();
- Signature = reader.ReadBytes (sig_length);
BlockIndex = reader.ReadLeb128 ();
}
{
bw.WriteLeb128 (Index);
bw.Write (Name);
- bw.WriteLeb128 ((int) Signature.Length);
- bw.Write (Signature);
bw.WriteLeb128 (BlockIndex);
}
public override string ToString ()
{
- return String.Format ("[LocalVariable {0}]", Name);
+ return String.Format ("[LocalVariable {0}:{1}:{2}]",
+ Name, Index, BlockIndex - 1);
}
}
- public class SourceFileEntry
+ public struct CapturedVariable
+ {
+ #region This is actually written to the symbol file
+ public readonly string Name;
+ public readonly string CapturedName;
+ public readonly CapturedKind Kind;
+ #endregion
+
+ public enum CapturedKind : byte
+ {
+ Local,
+ Parameter,
+ This
+ }
+
+ public CapturedVariable (string name, string captured_name,
+ CapturedKind kind)
+ {
+ this.Name = name;
+ this.CapturedName = captured_name;
+ this.Kind = kind;
+ }
+
+ internal CapturedVariable (MyBinaryReader reader)
+ {
+ Name = reader.ReadString ();
+ CapturedName = reader.ReadString ();
+ Kind = (CapturedKind) reader.ReadByte ();
+ }
+
+ internal void Write (MyBinaryWriter bw)
+ {
+ bw.Write (Name);
+ bw.Write (CapturedName);
+ bw.Write ((byte) Kind);
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("[CapturedVariable {0}:{1}:{2}]",
+ Name, CapturedName, Kind);
+ }
+ }
+
+ public struct CapturedScope
{
#region This is actually written to the symbol file
+ public readonly int Scope;
+ public readonly string CapturedName;
+ #endregion
+
+ public CapturedScope (int scope, string captured_name)
+ {
+ this.Scope = scope;
+ this.CapturedName = captured_name;
+ }
+
+ internal CapturedScope (MyBinaryReader reader)
+ {
+ Scope = reader.ReadLeb128 ();
+ CapturedName = reader.ReadString ();
+ }
+
+ internal void Write (MyBinaryWriter bw)
+ {
+ bw.WriteLeb128 (Scope);
+ bw.Write (CapturedName);
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("[CapturedScope {0}:{1}]",
+ Scope, CapturedName);
+ }
+ }
+
+ public struct ScopeVariable
+ {
+ #region This is actually written to the symbol file
+ public readonly int Scope;
public readonly int Index;
- int Count;
- int NamespaceCount;
- int NameOffset;
- int MethodOffset;
- int NamespaceTableOffset;
+ #endregion
+
+ public ScopeVariable (int scope, int index)
+ {
+ this.Scope = scope;
+ this.Index = index;
+ }
+
+ internal ScopeVariable (MyBinaryReader reader)
+ {
+ Scope = reader.ReadLeb128 ();
+ Index = reader.ReadLeb128 ();
+ }
+
+ internal void Write (MyBinaryWriter bw)
+ {
+ bw.WriteLeb128 (Scope);
+ bw.WriteLeb128 (Index);
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("[ScopeVariable {0}:{1}]", Scope, Index);
+ }
+ }
+
+ public class AnonymousScopeEntry
+ {
+ #region This is actually written to the symbol file
+ public readonly int ID;
+ #endregion
+
+ List<CapturedVariable> captured_vars = new List<CapturedVariable> ();
+ List<CapturedScope> captured_scopes = new List<CapturedScope> ();
+
+ public AnonymousScopeEntry (int id)
+ {
+ this.ID = id;
+ }
+
+ internal AnonymousScopeEntry (MyBinaryReader reader)
+ {
+ ID = reader.ReadLeb128 ();
+
+ int num_captured_vars = reader.ReadLeb128 ();
+ for (int i = 0; i < num_captured_vars; i++)
+ captured_vars.Add (new CapturedVariable (reader));
+
+ int num_captured_scopes = reader.ReadLeb128 ();
+ for (int i = 0; i < num_captured_scopes; i++)
+ captured_scopes.Add (new CapturedScope (reader));
+ }
+
+ internal void AddCapturedVariable (string name, string captured_name,
+ CapturedVariable.CapturedKind kind)
+ {
+ captured_vars.Add (new CapturedVariable (name, captured_name, kind));
+ }
+
+ public CapturedVariable[] CapturedVariables {
+ get {
+ CapturedVariable[] retval = new CapturedVariable [captured_vars.Count];
+ captured_vars.CopyTo (retval, 0);
+ return retval;
+ }
+ }
+
+ internal void AddCapturedScope (int scope, string captured_name)
+ {
+ captured_scopes.Add (new CapturedScope (scope, captured_name));
+ }
+
+ public CapturedScope[] CapturedScopes {
+ get {
+ CapturedScope[] retval = new CapturedScope [captured_scopes.Count];
+ captured_scopes.CopyTo (retval, 0);
+ return retval;
+ }
+ }
+
+ internal void Write (MyBinaryWriter bw)
+ {
+ bw.WriteLeb128 (ID);
+
+ bw.WriteLeb128 (captured_vars.Count);
+ foreach (CapturedVariable cv in captured_vars)
+ cv.Write (bw);
+
+ bw.WriteLeb128 (captured_scopes.Count);
+ foreach (CapturedScope cs in captured_scopes)
+ cs.Write (bw);
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("[AnonymousScope {0}]", ID);
+ }
+ }
+
+ public class CompileUnitEntry : ICompileUnit
+ {
+ #region This is actually written to the symbol file
+ public readonly int Index;
+ int DataOffset;
#endregion
MonoSymbolFile file;
- string file_name;
- ArrayList methods;
- ArrayList namespaces;
+ SourceFileEntry source;
+ List<SourceFileEntry> include_files;
+ List<NamespaceEntry> namespaces;
+
bool creating;
public static int Size {
- get { return 24; }
+ get { return 8; }
}
- public SourceFileEntry (MonoSymbolFile file, string file_name)
+ CompileUnitEntry ICompileUnit.Entry {
+ get { return this; }
+ }
+
+ public CompileUnitEntry (MonoSymbolFile file, SourceFileEntry source)
{
this.file = file;
- this.file_name = file_name;
- this.Index = file.AddSource (this);
+ this.source = source;
+
+ this.Index = file.AddCompileUnit (this);
creating = true;
- methods = new ArrayList ();
- namespaces = new ArrayList ();
+ namespaces = new List<NamespaceEntry> ();
}
- public void DefineMethod (string name, int token, LocalVariableEntry[] locals,
- LineNumberEntry[] lines, LexicalBlockEntry[] blocks,
- int start, int end, int namespace_id)
+ public void AddFile (SourceFileEntry file)
{
if (!creating)
throw new InvalidOperationException ();
- MethodEntry entry = new MethodEntry (
- file, this, name, (int) token, locals, lines, blocks,
- start, end, namespace_id);
+ if (include_files == null)
+ include_files = new List<SourceFileEntry> ();
+
+ include_files.Add (file);
+ }
+
+ public SourceFileEntry SourceFile {
+ get {
+ if (creating)
+ return source;
- methods.Add (entry);
- file.AddMethod (entry);
+ ReadData ();
+ return source;
+ }
}
public int DefineNamespace (string name, string[] using_clauses, int parent)
internal void WriteData (MyBinaryWriter bw)
{
- NameOffset = (int) bw.BaseStream.Position;
- bw.Write (file_name);
-
- ArrayList list = new ArrayList ();
- foreach (MethodEntry entry in methods)
- list.Add (entry.Write (file, bw));
- list.Sort ();
- Count = list.Count;
-
- MethodOffset = (int) bw.BaseStream.Position;
- foreach (MethodSourceEntry method in list)
- method.Write (bw);
+ DataOffset = (int) bw.BaseStream.Position;
+ bw.WriteLeb128 (source.Index);
+
+ int count_includes = include_files != null ? include_files.Count : 0;
+ bw.WriteLeb128 (count_includes);
+ if (include_files != null) {
+ foreach (SourceFileEntry entry in include_files)
+ bw.WriteLeb128 (entry.Index);
+ }
- NamespaceCount = namespaces.Count;
- NamespaceTableOffset = (int) bw.BaseStream.Position;
+ bw.WriteLeb128 (namespaces.Count);
foreach (NamespaceEntry ns in namespaces)
ns.Write (file, bw);
}
internal void Write (BinaryWriter bw)
{
bw.Write (Index);
- bw.Write (Count);
- bw.Write (NamespaceCount);
- bw.Write (NameOffset);
- bw.Write (MethodOffset);
- bw.Write (NamespaceTableOffset);
+ bw.Write (DataOffset);
}
- internal SourceFileEntry (MonoSymbolFile file, BinaryReader reader)
+ internal CompileUnitEntry (MonoSymbolFile file, MyBinaryReader reader)
{
this.file = file;
Index = reader.ReadInt32 ();
- Count = reader.ReadInt32 ();
- NamespaceCount = reader.ReadInt32 ();
- NameOffset = reader.ReadInt32 ();
- MethodOffset = reader.ReadInt32 ();
- NamespaceTableOffset = reader.ReadInt32 ();
-
- file_name = file.ReadString (NameOffset);
+ DataOffset = reader.ReadInt32 ();
}
- public string FileName {
- get { return file_name; }
- }
+ void ReadData ()
+ {
+ if (creating)
+ throw new InvalidOperationException ();
- public MethodSourceEntry[] Methods {
- get {
- if (creating)
- throw new InvalidOperationException ();
+ lock (file) {
+ if (namespaces != null)
+ return;
- BinaryReader reader = file.BinaryReader;
+ MyBinaryReader reader = file.BinaryReader;
int old_pos = (int) reader.BaseStream.Position;
- reader.BaseStream.Position = MethodOffset;
- ArrayList list = new ArrayList ();
- for (int i = 0; i < Count; i ++)
- list.Add (new MethodSourceEntry (reader));
- reader.BaseStream.Position = old_pos;
+ reader.BaseStream.Position = DataOffset;
- MethodSourceEntry[] retval = new MethodSourceEntry [Count];
- list.CopyTo (retval, 0);
- return retval;
- }
- }
+ int source_idx = reader.ReadLeb128 ();
+ source = file.GetSourceFile (source_idx);
- public NamespaceEntry[] Namespaces {
- get {
- if (creating)
- throw new InvalidOperationException ();
+ int count_includes = reader.ReadLeb128 ();
+ if (count_includes > 0) {
+ include_files = new List<SourceFileEntry> ();
+ for (int i = 0; i < count_includes; i++)
+ include_files.Add (file.GetSourceFile (reader.ReadLeb128 ()));
+ }
- MyBinaryReader reader = file.BinaryReader;
- int old_pos = (int) reader.BaseStream.Position;
+ int count_ns = reader.ReadLeb128 ();
+ namespaces = new List<NamespaceEntry> ();
+ for (int i = 0; i < count_ns; i ++)
+ namespaces.Add (new NamespaceEntry (file, reader));
- reader.BaseStream.Position = NamespaceTableOffset;
- ArrayList list = new ArrayList ();
- for (int i = 0; i < NamespaceCount; i ++)
- list.Add (new NamespaceEntry (file, reader));
reader.BaseStream.Position = old_pos;
+ }
+ }
- NamespaceEntry[] retval = new NamespaceEntry [list.Count];
- list.CopyTo (retval, 0);
+ public NamespaceEntry[] Namespaces {
+ get {
+ ReadData ();
+ NamespaceEntry[] retval = new NamespaceEntry [namespaces.Count];
+ namespaces.CopyTo (retval, 0);
return retval;
}
}
- public override string ToString ()
- {
- return String.Format ("SourceFileEntry ({0}:{1}:{2})",
- Index, file_name, Count);
+ public SourceFileEntry[] IncludeFiles {
+ get {
+ ReadData ();
+ if (include_files == null)
+ return new SourceFileEntry [0];
+
+ SourceFileEntry[] retval = new SourceFileEntry [include_files.Count];
+ include_files.CopyTo (retval, 0);
+ return retval;
+ }
}
}
- public struct MethodSourceEntry : IComparable
+ public class SourceFileEntry
{
#region This is actually written to the symbol file
public readonly int Index;
- public readonly int FileOffset;
- public readonly int StartRow;
- public readonly int EndRow;
+ int DataOffset;
#endregion
- public MethodSourceEntry (int index, int file_offset, int start, int end)
+ MonoSymbolFile file;
+ string file_name;
+ byte[] guid;
+ byte[] hash;
+ bool creating;
+ bool auto_generated;
+
+ public static int Size {
+ get { return 8; }
+ }
+
+ public SourceFileEntry (MonoSymbolFile file, string file_name)
{
- this.Index = index;
- this.FileOffset = file_offset;
- this.StartRow = start;
- this.EndRow = end;
+ this.file = file;
+ this.file_name = file_name;
+ this.Index = file.AddSource (this);
+
+ creating = true;
}
- internal MethodSourceEntry (BinaryReader reader)
+ public SourceFileEntry (MonoSymbolFile file, string file_name,
+ byte[] guid, byte[] checksum)
+ : this (file, file_name)
{
- Index = reader.ReadInt32 ();
- FileOffset = reader.ReadInt32 ();
- StartRow = reader.ReadInt32 ();
- EndRow = reader.ReadInt32 ();
+ this.guid = guid;
+ this.hash = checksum;
}
- public static int Size {
- get { return 16; }
+ internal void WriteData (MyBinaryWriter bw)
+ {
+ DataOffset = (int) bw.BaseStream.Position;
+ bw.Write (file_name);
+
+ if (guid == null) {
+ guid = Guid.NewGuid ().ToByteArray ();
+ try {
+ using (FileStream fs = new FileStream (file_name, FileMode.Open, FileAccess.Read)) {
+ MD5 md5 = MD5.Create ();
+ hash = md5.ComputeHash (fs);
+ }
+ } catch {
+ hash = new byte [16];
+ }
+ }
+
+ bw.Write (guid);
+ bw.Write (hash);
+ bw.Write ((byte) (auto_generated ? 1 : 0));
}
internal void Write (BinaryWriter bw)
{
bw.Write (Index);
- bw.Write (FileOffset);
- bw.Write (StartRow);
- bw.Write (EndRow);
+ bw.Write (DataOffset);
}
- public int CompareTo (object obj)
+ internal SourceFileEntry (MonoSymbolFile file, MyBinaryReader reader)
{
- MethodSourceEntry method = (MethodSourceEntry) obj;
+ this.file = file;
- if (method.StartRow < StartRow)
- return -1;
- else if (method.StartRow > StartRow)
- return 1;
- else
- return 0;
+ Index = reader.ReadInt32 ();
+ DataOffset = reader.ReadInt32 ();
+
+ int old_pos = (int) reader.BaseStream.Position;
+ reader.BaseStream.Position = DataOffset;
+
+ file_name = reader.ReadString ();
+ guid = reader.ReadBytes (16);
+ hash = reader.ReadBytes (16);
+ auto_generated = reader.ReadByte () == 1;
+
+ reader.BaseStream.Position = old_pos;
+ }
+
+ public string FileName {
+ get { return file_name; }
+ }
+
+ public bool AutoGenerated {
+ get { return auto_generated; }
+ }
+
+ public void SetAutoGenerated ()
+ {
+ if (!creating)
+ throw new InvalidOperationException ();
+
+ auto_generated = true;
+ file.OffsetTable.FileFlags |= OffsetTable.Flags.IsAspxSource;
+ }
+
+ public bool CheckChecksum ()
+ {
+ try {
+ using (FileStream fs = new FileStream (file_name, FileMode.Open)) {
+ MD5 md5 = MD5.Create ();
+ byte[] data = md5.ComputeHash (fs);
+ for (int i = 0; i < 16; i++)
+ if (data [i] != hash [i])
+ return false;
+ return true;
+ }
+ } catch {
+ return false;
+ }
}
public override string ToString ()
{
- return String.Format ("MethodSourceEntry ({0}:{1}:{2}:{3})",
- Index, FileOffset, StartRow, EndRow);
+ return String.Format ("SourceFileEntry ({0}:{1})", Index, DataOffset);
}
}
- public struct MethodIndexEntry
+ public class LineNumberTable
{
- #region This is actually written to the symbol file
- public readonly int FileOffset;
- public readonly int Token;
- #endregion
+ protected LineNumberEntry[] _line_numbers;
+ public LineNumberEntry[] LineNumbers {
+ get { return _line_numbers; }
+ }
- public static int Size {
- get { return 8; }
+ public readonly int LineBase;
+ public readonly int LineRange;
+ public readonly byte OpcodeBase;
+ public readonly int MaxAddressIncrement;
+
+#region Configurable constants
+ public const int Default_LineBase = -1;
+ public const int Default_LineRange = 8;
+ public const byte Default_OpcodeBase = 9;
+
+ public const bool SuppressDuplicates = true;
+#endregion
+
+ public const byte DW_LNS_copy = 1;
+ public const byte DW_LNS_advance_pc = 2;
+ public const byte DW_LNS_advance_line = 3;
+ public const byte DW_LNS_set_file = 4;
+ public const byte DW_LNS_const_add_pc = 8;
+
+ public const byte DW_LNE_end_sequence = 1;
+
+ // MONO extensions.
+ public const byte DW_LNE_MONO_negate_is_hidden = 0x40;
+
+ internal const byte DW_LNE_MONO__extensions_start = 0x40;
+ internal const byte DW_LNE_MONO__extensions_end = 0x7f;
+
+ protected LineNumberTable (MonoSymbolFile file)
+ {
+ this.LineBase = file.OffsetTable.LineNumberTable_LineBase;
+ this.LineRange = file.OffsetTable.LineNumberTable_LineRange;
+ this.OpcodeBase = (byte) file.OffsetTable.LineNumberTable_OpcodeBase;
+ this.MaxAddressIncrement = (255 - OpcodeBase) / LineRange;
}
- public MethodIndexEntry (int offset, int token)
+ internal LineNumberTable (MonoSymbolFile file, LineNumberEntry[] lines)
+ : this (file)
{
- this.FileOffset = offset;
- this.Token = token;
+ this._line_numbers = lines;
}
- internal MethodIndexEntry (BinaryReader reader)
+ internal void Write (MonoSymbolFile file, MyBinaryWriter bw)
{
- FileOffset = reader.ReadInt32 ();
- Token = reader.ReadInt32 ();
+ int start = (int) bw.BaseStream.Position;
+
+ bool last_is_hidden = false;
+ int last_line = 1, last_offset = 0, last_file = 1;
+ for (int i = 0; i < LineNumbers.Length; i++) {
+ int line_inc = LineNumbers [i].Row - last_line;
+ int offset_inc = LineNumbers [i].Offset - last_offset;
+
+ if (SuppressDuplicates && (i+1 < LineNumbers.Length)) {
+ if (LineNumbers [i+1].Equals (LineNumbers [i]))
+ continue;
+ }
+
+ if (LineNumbers [i].File != last_file) {
+ bw.Write (DW_LNS_set_file);
+ bw.WriteLeb128 (LineNumbers [i].File);
+ last_file = LineNumbers [i].File;
+ }
+
+ if (LineNumbers [i].IsHidden != last_is_hidden) {
+ bw.Write ((byte) 0);
+ bw.Write ((byte) 1);
+ bw.Write (DW_LNE_MONO_negate_is_hidden);
+ last_is_hidden = LineNumbers [i].IsHidden;
+ }
+
+ if (offset_inc >= MaxAddressIncrement) {
+ if (offset_inc < 2 * MaxAddressIncrement) {
+ bw.Write (DW_LNS_const_add_pc);
+ offset_inc -= MaxAddressIncrement;
+ } else {
+ bw.Write (DW_LNS_advance_pc);
+ bw.WriteLeb128 (offset_inc);
+ offset_inc = 0;
+ }
+ }
+
+ if ((line_inc < LineBase) || (line_inc >= LineBase + LineRange)) {
+ bw.Write (DW_LNS_advance_line);
+ bw.WriteLeb128 (line_inc);
+ if (offset_inc != 0) {
+ bw.Write (DW_LNS_advance_pc);
+ bw.WriteLeb128 (offset_inc);
+ }
+ bw.Write (DW_LNS_copy);
+ } else {
+ byte opcode;
+ opcode = (byte) (line_inc - LineBase + (LineRange * offset_inc) +
+ OpcodeBase);
+ bw.Write (opcode);
+ }
+
+ last_line = LineNumbers [i].Row;
+ last_offset = LineNumbers [i].Offset;
+ }
+
+ bw.Write ((byte) 0);
+ bw.Write ((byte) 1);
+ bw.Write (DW_LNE_end_sequence);
+
+ file.ExtendedLineNumberSize += (int) bw.BaseStream.Position - start;
}
- internal void Write (BinaryWriter bw)
+ internal static LineNumberTable Read (MonoSymbolFile file, MyBinaryReader br)
{
- bw.Write (FileOffset);
- bw.Write (Token);
+ LineNumberTable lnt = new LineNumberTable (file);
+ lnt.DoRead (file, br);
+ return lnt;
}
- public override string ToString ()
+ void DoRead (MonoSymbolFile file, MyBinaryReader br)
+ {
+ var lines = new List<LineNumberEntry> ();
+
+ bool is_hidden = false, modified = false;
+ int stm_line = 1, stm_offset = 0, stm_file = 1;
+ while (true) {
+ byte opcode = br.ReadByte ();
+
+ if (opcode == 0) {
+ byte size = br.ReadByte ();
+ long end_pos = br.BaseStream.Position + size;
+ opcode = br.ReadByte ();
+
+ if (opcode == DW_LNE_end_sequence) {
+ if (modified)
+ lines.Add (new LineNumberEntry (
+ stm_file, stm_line, stm_offset, is_hidden));
+ break;
+ } else if (opcode == DW_LNE_MONO_negate_is_hidden) {
+ is_hidden = !is_hidden;
+ modified = true;
+ } else if ((opcode >= DW_LNE_MONO__extensions_start) &&
+ (opcode <= DW_LNE_MONO__extensions_end)) {
+ ; // reserved for future extensions
+ } else {
+ throw new MonoSymbolFileException (
+ "Unknown extended opcode {0:x} in LNT ({1})",
+ opcode, file.FileName);
+ }
+
+ br.BaseStream.Position = end_pos;
+ continue;
+ } else if (opcode < OpcodeBase) {
+ switch (opcode) {
+ case DW_LNS_copy:
+ lines.Add (new LineNumberEntry (
+ stm_file, stm_line, stm_offset, is_hidden));
+ modified = false;
+ break;
+ case DW_LNS_advance_pc:
+ stm_offset += br.ReadLeb128 ();
+ modified = true;
+ break;
+ case DW_LNS_advance_line:
+ stm_line += br.ReadLeb128 ();
+ modified = true;
+ break;
+ case DW_LNS_set_file:
+ stm_file = br.ReadLeb128 ();
+ modified = true;
+ break;
+ case DW_LNS_const_add_pc:
+ stm_offset += MaxAddressIncrement;
+ modified = true;
+ break;
+ default:
+ throw new MonoSymbolFileException (
+ "Unknown standard opcode {0:x} in LNT",
+ opcode);
+ }
+ } else {
+ opcode -= OpcodeBase;
+
+ stm_offset += opcode / LineRange;
+ stm_line += LineBase + (opcode % LineRange);
+ lines.Add (new LineNumberEntry (
+ stm_file, stm_line, stm_offset, is_hidden));
+ modified = false;
+ }
+ }
+
+ _line_numbers = new LineNumberEntry [lines.Count];
+ lines.CopyTo (_line_numbers, 0);
+ }
+
+ public bool GetMethodBounds (out LineNumberEntry start, out LineNumberEntry end)
{
- return String.Format ("MethodIndexEntry ({0}:{1:x})",
- FileOffset, Token);
+ if (_line_numbers.Length > 1) {
+ start = _line_numbers [0];
+ end = _line_numbers [_line_numbers.Length - 1];
+ return true;
+ }
+
+ start = LineNumberEntry.Null;
+ end = LineNumberEntry.Null;
+ return false;
}
}
public class MethodEntry : IComparable
{
#region This is actually written to the symbol file
- public readonly int SourceFileIndex;
+ public readonly int CompileUnitIndex;
public readonly int Token;
- public readonly int StartRow;
- public readonly int EndRow;
- public readonly int NumLocals;
- public readonly int NumLineNumbers;
public readonly int NamespaceID;
- public readonly bool LocalNamesAmbiguous;
- int NameOffset;
- int TypeIndexTableOffset;
+ int DataOffset;
int LocalVariableTableOffset;
int LineNumberTableOffset;
- int NumLexicalBlocks;
- int LexicalBlockTableOffset;
+ int CodeBlockTableOffset;
+ int ScopeVariableTableOffset;
+ int RealNameOffset;
+ Flags flags;
#endregion
int index;
- int file_offset;
- public readonly SourceFileEntry SourceFile;
- public readonly LineNumberEntry[] LineNumbers;
- public readonly int[] LocalTypeIndices;
- public readonly LocalVariableEntry[] Locals;
- public readonly LexicalBlockEntry[] LexicalBlocks;
+ public Flags MethodFlags {
+ get { return flags; }
+ }
+
+ public readonly CompileUnitEntry CompileUnit;
+
+ LocalVariableEntry[] locals;
+ CodeBlockEntry[] code_blocks;
+ ScopeVariable[] scope_vars;
+ LineNumberTable lnt;
+ string real_name;
public readonly MonoSymbolFile SymbolFile;
set { index = value; }
}
- public static int Size {
- get { return 52; }
+ [Flags]
+ public enum Flags
+ {
+ LocalNamesAmbiguous = 1
}
+ public const int Size = 12;
+
internal MethodEntry (MonoSymbolFile file, MyBinaryReader reader, int index)
{
this.SymbolFile = file;
this.index = index;
- SourceFileIndex = reader.ReadInt32 ();
+
Token = reader.ReadInt32 ();
- StartRow = reader.ReadInt32 ();
- EndRow = reader.ReadInt32 ();
- NumLocals = reader.ReadInt32 ();
- NumLineNumbers = reader.ReadInt32 ();
- NameOffset = reader.ReadInt32 ();
- TypeIndexTableOffset = reader.ReadInt32 ();
- LocalVariableTableOffset = reader.ReadInt32 ();
+ DataOffset = reader.ReadInt32 ();
LineNumberTableOffset = reader.ReadInt32 ();
- NumLexicalBlocks = reader.ReadInt32 ();
- LexicalBlockTableOffset = reader.ReadInt32 ();
- NamespaceID = reader.ReadInt32 ();
- LocalNamesAmbiguous = reader.ReadInt32 () != 0;
- SourceFile = file.GetSourceFile (SourceFileIndex);
+ long old_pos = reader.BaseStream.Position;
+ reader.BaseStream.Position = DataOffset;
- if (LineNumberTableOffset != 0) {
- long old_pos = reader.BaseStream.Position;
- reader.BaseStream.Position = LineNumberTableOffset;
+ CompileUnitIndex = reader.ReadLeb128 ();
+ LocalVariableTableOffset = reader.ReadLeb128 ();
+ NamespaceID = reader.ReadLeb128 ();
- LineNumbers = new LineNumberEntry [NumLineNumbers];
+ CodeBlockTableOffset = reader.ReadLeb128 ();
+ ScopeVariableTableOffset = reader.ReadLeb128 ();
- for (int i = 0; i < NumLineNumbers; i++)
- LineNumbers [i] = new LineNumberEntry (reader);
+ RealNameOffset = reader.ReadLeb128 ();
- reader.BaseStream.Position = old_pos;
- }
+ flags = (Flags) reader.ReadLeb128 ();
- if (LocalVariableTableOffset != 0) {
- long old_pos = reader.BaseStream.Position;
- reader.BaseStream.Position = LocalVariableTableOffset;
-
- Locals = new LocalVariableEntry [NumLocals];
-
- for (int i = 0; i < NumLocals; i++)
- Locals [i] = new LocalVariableEntry (reader);
-
- reader.BaseStream.Position = old_pos;
- }
-
- if (TypeIndexTableOffset != 0) {
- long old_pos = reader.BaseStream.Position;
- reader.BaseStream.Position = TypeIndexTableOffset;
+ reader.BaseStream.Position = old_pos;
- LocalTypeIndices = new int [NumLocals];
-
- for (int i = 0; i < NumLocals; i++)
- LocalTypeIndices [i] = reader.ReadInt32 ();
-
- reader.BaseStream.Position = old_pos;
- }
-
- if (LexicalBlockTableOffset != 0) {
- long old_pos = reader.BaseStream.Position;
- reader.BaseStream.Position = LexicalBlockTableOffset;
-
- LexicalBlocks = new LexicalBlockEntry [NumLexicalBlocks];
- for (int i = 0; i < NumLexicalBlocks; i++)
- LexicalBlocks [i] = new LexicalBlockEntry (i, reader);
-
- reader.BaseStream.Position = old_pos;
- }
+ CompileUnit = file.GetCompileUnit (CompileUnitIndex);
}
- internal MethodEntry (MonoSymbolFile file, SourceFileEntry source,
- string name, int token, LocalVariableEntry[] locals,
- LineNumberEntry[] lines, LexicalBlockEntry[] blocks,
- int start_row, int end_row, int namespace_id)
+ internal MethodEntry (MonoSymbolFile file, CompileUnitEntry comp_unit,
+ int token, ScopeVariable[] scope_vars,
+ LocalVariableEntry[] locals, LineNumberEntry[] lines,
+ CodeBlockEntry[] code_blocks, string real_name,
+ Flags flags, int namespace_id)
{
this.SymbolFile = file;
+ this.real_name = real_name;
+ this.locals = locals;
+ this.code_blocks = code_blocks;
+ this.scope_vars = scope_vars;
+ this.flags = flags;
index = -1;
Token = token;
- SourceFileIndex = source.Index;
- SourceFile = source;
- StartRow = start_row;
- EndRow = end_row;
+ CompileUnitIndex = comp_unit.Index;
+ CompileUnit = comp_unit;
NamespaceID = namespace_id;
- LexicalBlocks = blocks;
- NumLexicalBlocks = LexicalBlocks != null ? LexicalBlocks.Length : 0;
-
- LineNumbers = BuildLineNumberTable (lines);
- NumLineNumbers = LineNumbers.Length;
- file.NumLineNumbers += NumLineNumbers;
+ CheckLineNumberTable (lines);
+ lnt = new LineNumberTable (file, lines);
+ file.NumLineNumbers += lines.Length;
- NumLocals = locals != null ? locals.Length : 0;
- Locals = locals;
+ int num_locals = locals != null ? locals.Length : 0;
- if (NumLocals <= 32) {
+ if (num_locals <= 32) {
// Most of the time, the O(n^2) factor is actually
// less than the cost of allocating the hash table,
// 32 is a rough number obtained through some testing.
- for (int i = 0; i < NumLocals; i ++) {
+ for (int i = 0; i < num_locals; i ++) {
string nm = locals [i].Name;
- for (int j = i + 1; j < NumLocals; j ++) {
+ for (int j = i + 1; j < num_locals; j ++) {
if (locals [j].Name == nm) {
- LocalNamesAmbiguous = true;
+ flags |= Flags.LocalNamesAmbiguous;
goto locals_check_done;
}
}
locals_check_done :
;
} else {
- Hashtable local_names = new Hashtable ();
+ var local_names = new Dictionary<string, LocalVariableEntry> ();
foreach (LocalVariableEntry local in locals) {
- if (local_names.Contains (local.Name)) {
- LocalNamesAmbiguous = true;
+ if (local_names.ContainsKey (local.Name)) {
+ flags |= Flags.LocalNamesAmbiguous;
break;
}
local_names.Add (local.Name, local);
}
}
-
- LocalTypeIndices = new int [NumLocals];
- for (int i = 0; i < NumLocals; i++)
- LocalTypeIndices [i] = file.GetNextTypeIndex ();
}
- static LineNumberEntry [] tmp_buff = new LineNumberEntry [20];
-
- // BuildLineNumberTable() eliminates duplicate line numbers and ensures
- // we aren't going "backwards" since this would counfuse the runtime's
- // debugging code (and the debugger).
- //
- // In the line number table, the "offset" field most be strictly
- // monotonic increasing; that is, the next entry must not have an offset
- // which is equal to or less than the current one.
- //
- // The most common case is that our input (ie. the line number table as
- // we get it from mcs) contains several entries with the same offset
- // (and different line numbers) - but it may also happen that the offset
- // is decreasing (this can be considered as an exception, such lines will
- // simply be discarded).
- LineNumberEntry[] BuildLineNumberTable (LineNumberEntry[] line_numbers)
- {
- int pos = 0;
+ void CheckLineNumberTable (LineNumberEntry[] line_numbers)
+ {
int last_offset = -1;
int last_row = -1;
if (line_numbers == null)
- return new LineNumberEntry [0];
+ return;
- if (tmp_buff.Length < (line_numbers.Length + 1))
- tmp_buff = new LineNumberEntry [(line_numbers.Length + 1) * 2];
-
for (int i = 0; i < line_numbers.Length; i++) {
LineNumberEntry line = line_numbers [i];
+ if (line.Equals (LineNumberEntry.Null))
+ throw new MonoSymbolFileException ();
+
+ if (line.Offset < last_offset)
+ throw new MonoSymbolFileException ();
+
if (line.Offset > last_offset) {
- if (last_row >= 0)
- tmp_buff [pos ++] = new LineNumberEntry (last_row, last_offset);
last_row = line.Row;
last_offset = line.Offset;
} else if (line.Row > last_row) {
last_row = line.Row;
}
}
+ }
- if (last_row >= 0)
- tmp_buff [pos ++] = new LineNumberEntry (last_row, last_offset);
+ internal void Write (MyBinaryWriter bw)
+ {
+ if ((index <= 0) || (DataOffset == 0))
+ throw new InvalidOperationException ();
- LineNumberEntry [] retval = new LineNumberEntry [pos];
- Array.Copy (tmp_buff, retval, pos);
- return retval;
+ bw.Write (Token);
+ bw.Write (DataOffset);
+ bw.Write (LineNumberTableOffset);
}
- internal MethodSourceEntry Write (MonoSymbolFile file, MyBinaryWriter bw)
+ internal void WriteData (MonoSymbolFile file, MyBinaryWriter bw)
{
if (index <= 0)
throw new InvalidOperationException ();
- NameOffset = (int) bw.BaseStream.Position;
+ LocalVariableTableOffset = (int) bw.BaseStream.Position;
+ int num_locals = locals != null ? locals.Length : 0;
+ bw.WriteLeb128 (num_locals);
+ for (int i = 0; i < num_locals; i++)
+ locals [i].Write (file, bw);
+ file.LocalCount += num_locals;
+
+ CodeBlockTableOffset = (int) bw.BaseStream.Position;
+ int num_code_blocks = code_blocks != null ? code_blocks.Length : 0;
+ bw.WriteLeb128 (num_code_blocks);
+ for (int i = 0; i < num_code_blocks; i++)
+ code_blocks [i].Write (bw);
+
+ ScopeVariableTableOffset = (int) bw.BaseStream.Position;
+ int num_scope_vars = scope_vars != null ? scope_vars.Length : 0;
+ bw.WriteLeb128 (num_scope_vars);
+ for (int i = 0; i < num_scope_vars; i++)
+ scope_vars [i].Write (bw);
+
+ if (real_name != null) {
+ RealNameOffset = (int) bw.BaseStream.Position;
+ bw.Write (real_name);
+ }
- TypeIndexTableOffset = (int) bw.BaseStream.Position;
+ LineNumberTableOffset = (int) bw.BaseStream.Position;
+ lnt.Write (file, bw);
- for (int i = 0; i < NumLocals; i++)
- bw.Write (LocalTypeIndices [i]);
+ DataOffset = (int) bw.BaseStream.Position;
- LocalVariableTableOffset = (int) bw.BaseStream.Position;
- for (int i = 0; i < NumLocals; i++)
- Locals [i].Write (file, bw);
- file.LocalCount += NumLocals;
+ bw.WriteLeb128 (CompileUnitIndex);
+ bw.WriteLeb128 (LocalVariableTableOffset);
+ bw.WriteLeb128 (NamespaceID);
- LineNumberTableOffset = (int) bw.BaseStream.Position;
- for (int i = 0; i < NumLineNumbers; i++)
- LineNumbers [i].Write (bw);
- file.LineNumberCount += NumLineNumbers;
+ bw.WriteLeb128 (CodeBlockTableOffset);
+ bw.WriteLeb128 (ScopeVariableTableOffset);
- LexicalBlockTableOffset = (int) bw.BaseStream.Position;
- for (int i = 0; i < NumLexicalBlocks; i++)
- LexicalBlocks [i].Write (bw);
- file_offset = (int) bw.BaseStream.Position;
+ bw.WriteLeb128 (RealNameOffset);
+ bw.WriteLeb128 ((int) flags);
+ }
- bw.Write (SourceFileIndex);
- bw.Write (Token);
- bw.Write (StartRow);
- bw.Write (EndRow);
- bw.Write (NumLocals);
- bw.Write (NumLineNumbers);
- bw.Write (NameOffset);
- bw.Write (TypeIndexTableOffset);
- bw.Write (LocalVariableTableOffset);
- bw.Write (LineNumberTableOffset);
- bw.Write (NumLexicalBlocks);
- bw.Write (LexicalBlockTableOffset);
- bw.Write (NamespaceID);
- bw.Write (LocalNamesAmbiguous ? 1 : 0);
+ public LineNumberTable GetLineNumberTable ()
+ {
+ lock (SymbolFile) {
+ if (lnt != null)
+ return lnt;
+
+ if (LineNumberTableOffset == 0)
+ return null;
+
+ MyBinaryReader reader = SymbolFile.BinaryReader;
+ long old_pos = reader.BaseStream.Position;
+ reader.BaseStream.Position = LineNumberTableOffset;
+
+ lnt = LineNumberTable.Read (SymbolFile, reader);
+
+ reader.BaseStream.Position = old_pos;
+ return lnt;
+ }
+ }
+
+ public LocalVariableEntry[] GetLocals ()
+ {
+ lock (SymbolFile) {
+ if (locals != null)
+ return locals;
+
+ if (LocalVariableTableOffset == 0)
+ return null;
+
+ MyBinaryReader reader = SymbolFile.BinaryReader;
+ long old_pos = reader.BaseStream.Position;
+ reader.BaseStream.Position = LocalVariableTableOffset;
+
+ int num_locals = reader.ReadLeb128 ();
+ locals = new LocalVariableEntry [num_locals];
+
+ for (int i = 0; i < num_locals; i++)
+ locals [i] = new LocalVariableEntry (SymbolFile, reader);
+
+ reader.BaseStream.Position = old_pos;
+ return locals;
+ }
+ }
+
+ public CodeBlockEntry[] GetCodeBlocks ()
+ {
+ lock (SymbolFile) {
+ if (code_blocks != null)
+ return code_blocks;
+
+ if (CodeBlockTableOffset == 0)
+ return null;
+
+ MyBinaryReader reader = SymbolFile.BinaryReader;
+ long old_pos = reader.BaseStream.Position;
+ reader.BaseStream.Position = CodeBlockTableOffset;
+
+ int num_code_blocks = reader.ReadLeb128 ();
+ code_blocks = new CodeBlockEntry [num_code_blocks];
+
+ for (int i = 0; i < num_code_blocks; i++)
+ code_blocks [i] = new CodeBlockEntry (i, reader);
+
+ reader.BaseStream.Position = old_pos;
+ return code_blocks;
+ }
+ }
- return new MethodSourceEntry (index, file_offset, StartRow, EndRow);
+ public ScopeVariable[] GetScopeVariables ()
+ {
+ lock (SymbolFile) {
+ if (scope_vars != null)
+ return scope_vars;
+
+ if (ScopeVariableTableOffset == 0)
+ return null;
+
+ MyBinaryReader reader = SymbolFile.BinaryReader;
+ long old_pos = reader.BaseStream.Position;
+ reader.BaseStream.Position = ScopeVariableTableOffset;
+
+ int num_scope_vars = reader.ReadLeb128 ();
+ scope_vars = new ScopeVariable [num_scope_vars];
+
+ for (int i = 0; i < num_scope_vars; i++)
+ scope_vars [i] = new ScopeVariable (reader);
+
+ reader.BaseStream.Position = old_pos;
+ return scope_vars;
+ }
}
- internal void WriteIndex (BinaryWriter bw)
+ public string GetRealName ()
{
- new MethodIndexEntry (file_offset, Token).Write (bw);
+ lock (SymbolFile) {
+ if (real_name != null)
+ return real_name;
+
+ if (RealNameOffset == 0)
+ return null;
+
+ real_name = SymbolFile.BinaryReader.ReadString (RealNameOffset);
+ return real_name;
+ }
}
public int CompareTo (object obj)
public override string ToString ()
{
- return String.Format ("[Method {0}:{1}:{2}:{3}:{4} - {6}:{7} - {5}]",
- index, Token, SourceFileIndex, StartRow, EndRow,
- SourceFile, NumLocals, NumLineNumbers);
+ return String.Format ("[Method {0}:{1:x}:{2}:{3}]",
+ index, Token, CompileUnitIndex, CompileUnit);
}
}