{
public struct OffsetTable
{
- public const int Version = 29;
+ public const int Version = 35;
public const long Magic = 0x45e82623fd7fa614;
public int TotalFileSize;
}
}
+ public class LexicalBlockEntry
+ {
+ public int Index;
+ public int StartOffset;
+ public int EndOffset;
+
+ public LexicalBlockEntry (int index, int start_offset)
+ {
+ this.Index = index;
+ this.StartOffset = start_offset;
+ }
+
+ internal LexicalBlockEntry (int index, BinaryReader reader)
+ {
+ this.Index = index;
+ this.StartOffset = reader.ReadInt32 ();
+ this.EndOffset = reader.ReadInt32 ();
+ }
+
+ public void Close (int end_offset)
+ {
+ this.EndOffset = end_offset;
+ }
+
+ internal void Write (BinaryWriter bw)
+ {
+ bw.Write (StartOffset);
+ bw.Write (EndOffset);
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("[LexicalBlock {0}:{1}]", StartOffset, EndOffset);
+ }
+ }
+
public struct LocalVariableEntry
{
public readonly string Name;
public readonly FieldAttributes Attributes;
public readonly byte[] Signature;
+ public readonly int BlockIndex;
- public LocalVariableEntry (string Name, FieldAttributes Attributes, byte[] Signature)
+ public LocalVariableEntry (string Name, FieldAttributes Attributes, byte[] Signature,
+ int BlockIndex)
{
this.Name = Name;
this.Attributes = Attributes;
this.Signature = Signature;
+ this.BlockIndex = BlockIndex;
}
internal LocalVariableEntry (BinaryReader reader)
Attributes = (FieldAttributes) reader.ReadInt32 ();
int sig_length = reader.ReadInt32 ();
Signature = reader.ReadBytes (sig_length);
+ BlockIndex = reader.ReadInt32 ();
}
internal void Write (MonoSymbolFile file, BinaryWriter bw)
bw.Write ((int) Attributes);
bw.Write ((int) Signature.Length);
bw.Write (Signature);
+ bw.Write (BlockIndex);
}
public override string ToString ()
MonoSymbolFile file;
string file_name;
ArrayList methods;
+ ArrayList namespaces;
int index, count, name_offset, method_offset;
+ int namespace_count, nstable_offset;
bool creating;
- internal static int Size {
- get { return 16; }
+ public static int Size {
+ get { return 24; }
}
- internal SourceFileEntry (MonoSymbolFile file, string file_name, int index)
+ internal SourceFileEntry (MonoSymbolFile file, string file_name)
{
this.file = file;
this.file_name = file_name;
- this.index = index;
+ this.index = file.AddSource (this);
creating = true;
methods = new ArrayList ();
+ namespaces = new ArrayList ();
}
public void DefineMethod (MethodBase method, int token, LocalVariableEntry[] locals,
- LineNumberEntry[] lines, int start, int end)
+ LineNumberEntry[] lines, LexicalBlockEntry[] blocks,
+ int start, int end, int namespace_id)
{
if (!creating)
throw new InvalidOperationException ();
MethodEntry entry = new MethodEntry (
- file, this, method, token, locals, lines, start, end);
+ file, this, method, token, locals, lines, blocks, start, end, namespace_id);
methods.Add (entry);
file.AddMethod (entry);
}
+ public int DefineNamespace (string name, string[] using_clauses, int parent)
+ {
+ if (!creating)
+ throw new InvalidOperationException ();
+
+ int index = file.GetNextNamespaceIndex ();
+ NamespaceEntry ns = new NamespaceEntry (name, index, using_clauses, parent);
+ namespaces.Add (ns);
+ return index;
+ }
+
internal void WriteData (BinaryWriter bw)
{
name_offset = (int) bw.BaseStream.Position;
method_offset = (int) bw.BaseStream.Position;
foreach (MethodSourceEntry method in list)
method.Write (bw);
+
+ namespace_count = namespaces.Count;
+ nstable_offset = (int) bw.BaseStream.Position;
+ foreach (NamespaceEntry ns in namespaces)
+ ns.Write (file, bw);
}
internal void Write (BinaryWriter bw)
{
bw.Write (index);
bw.Write (count);
+ bw.Write (namespace_count);
bw.Write (name_offset);
bw.Write (method_offset);
+ bw.Write (nstable_offset);
}
internal SourceFileEntry (MonoSymbolFile file, BinaryReader reader)
index = reader.ReadInt32 ();
count = reader.ReadInt32 ();
+ namespace_count = reader.ReadInt32 ();
name_offset = reader.ReadInt32 ();
method_offset = reader.ReadInt32 ();
+ nstable_offset = reader.ReadInt32 ();
file_name = file.ReadString (name_offset);
}
EndRow = reader.ReadInt32 ();
}
- public static int Size
- {
- get {
- return 16;
- }
+ public static int Size {
+ get { return 16; }
}
internal void Write (BinaryWriter bw)
}
}
+ public struct MethodIndexEntry
+ {
+ public readonly int FileOffset;
+ public readonly int FullNameOffset;
+ public readonly int Token;
+
+ public static int Size {
+ get { return 12; }
+ }
+
+ public MethodIndexEntry (int offset, int name_offset, int token)
+ {
+ this.FileOffset = offset;
+ this.FullNameOffset = name_offset;
+ this.Token = token;
+ }
+
+ internal MethodIndexEntry (BinaryReader reader)
+ {
+ FileOffset = reader.ReadInt32 ();
+ FullNameOffset = reader.ReadInt32 ();
+ Token = reader.ReadInt32 ();
+ }
+
+ internal void Write (BinaryWriter bw)
+ {
+ bw.Write (FileOffset);
+ bw.Write (FullNameOffset);
+ bw.Write (Token);
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("MethodIndexEntry ({0}:{1}:{2:x})",
+ FileOffset, FullNameOffset, Token);
+ }
+ }
+
public class MethodEntry
{
#region This is actually written to the symbol file
public readonly int Token;
public readonly int StartRow;
public readonly int EndRow;
- public readonly int ThisTypeIndex;
+ public readonly int ClassTypeIndex;
public readonly int NumParameters;
public readonly int NumLocals;
public readonly int NumLineNumbers;
+ public readonly int NamespaceID;
+ public readonly bool LocalNamesAmbiguous;
int NameOffset;
int FullNameOffset;
int TypeIndexTableOffset;
int LocalVariableTableOffset;
int LineNumberTableOffset;
+ int NumLexicalBlocks;
+ int LexicalBlockTableOffset;
#endregion
- int index;
int file_offset;
string name;
string full_name;
+ MethodIndexEntry index_entry;
+ public readonly int Index;
public readonly SourceFileEntry SourceFile;
public readonly LineNumberEntry[] LineNumbers;
public readonly int[] ParamTypeIndices;
public readonly int[] LocalTypeIndices;
public readonly LocalVariableEntry[] Locals;
+ public readonly Type[] LocalTypes;
+ public readonly LexicalBlockEntry[] LexicalBlocks;
- public static int Size
- {
- get {
- return 48;
- }
+ public readonly MonoSymbolFile SymbolFile;
+
+ public static int Size {
+ get { return 52; }
}
public string Name {
get { return full_name; }
}
+ public MethodBase MethodBase {
+ get { return SymbolFile.Assembly.MonoDebugger_GetMethod (Token); }
+ }
+
internal MethodEntry (MonoSymbolFile file, BinaryReader reader, int index)
{
- this.index = index;
+ this.SymbolFile = file;
+ this.Index = index;
SourceFileIndex = reader.ReadInt32 ();
Token = reader.ReadInt32 ();
StartRow = reader.ReadInt32 ();
EndRow = reader.ReadInt32 ();
- ThisTypeIndex = reader.ReadInt32 ();
+ ClassTypeIndex = reader.ReadInt32 ();
NumParameters = reader.ReadInt32 ();
NumLocals = reader.ReadInt32 ();
NumLineNumbers = reader.ReadInt32 ();
TypeIndexTableOffset = reader.ReadInt32 ();
LocalVariableTableOffset = reader.ReadInt32 ();
LineNumberTableOffset = reader.ReadInt32 ();
+ NumLexicalBlocks = reader.ReadInt32 ();
+ LexicalBlockTableOffset = reader.ReadInt32 ();
+ NamespaceID = reader.ReadInt32 ();
+ LocalNamesAmbiguous = reader.ReadInt32 () != 0;
name = file.ReadString (NameOffset);
full_name = file.ReadString (FullNameOffset);
reader.BaseStream.Position = LocalVariableTableOffset;
Locals = new LocalVariableEntry [NumLocals];
+ LocalTypes = new Type [NumLocals];
- for (int i = 0; i < NumLocals; i++)
+ Assembly ass = file.Assembly;
+
+ for (int i = 0; i < NumLocals; i++) {
Locals [i] = new LocalVariableEntry (reader);
+ LocalTypes [i] = ass.MonoDebugger_GetLocalTypeFromSignature (
+ Locals [i].Signature);
+ }
reader.BaseStream.Position = old_pos;
}
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;
+ }
}
internal MethodEntry (MonoSymbolFile file, SourceFileEntry source, MethodBase method,
int token, LocalVariableEntry[] locals, LineNumberEntry[] lines,
- int start_row, int end_row)
+ LexicalBlockEntry[] blocks, int start_row, int end_row,
+ int namespace_id)
{
- index = file.GetNextMethodIndex ();
+ this.SymbolFile = file;
+ Index = file.GetNextMethodIndex ();
Token = token;
SourceFileIndex = source.Index;
SourceFile = source;
StartRow = start_row;
EndRow = end_row;
+ NamespaceID = namespace_id;
+ LexicalBlocks = blocks;
+ NumLexicalBlocks = LexicalBlocks.Length;
- LineNumbers = BuildLineNumberTable (lines);
+ LineNumbers = lines;
NumLineNumbers = LineNumbers.Length;
ParameterInfo[] parameters = method.GetParameters ();
if (parameters == null)
parameters = new ParameterInfo [0];
-
- StringBuilder sb = new StringBuilder ();
- sb.Append (method.DeclaringType.FullName);
- sb.Append (".");
- sb.Append (method.Name);
- sb.Append ("(");
- for (int i = 0; i < parameters.Length; i++) {
- if (i > 0)
- sb.Append (",");
- sb.Append (parameters [i].ParameterType.FullName);
+
+ if (parameters.Length == 0)
+ full_name = method.DeclaringType.FullName + "." + method.Name + "()";
+ else if (parameters.Length == 1)
+ full_name = method.DeclaringType.FullName + "." + method.Name + "(" + parameters [0].ParameterType.FullName + ")";
+ else if (parameters.Length == 2)
+ full_name = method.DeclaringType.FullName + "." + method.Name + "(" + parameters [0].ParameterType.FullName + "," + parameters [1].ParameterType.FullName + ")";
+ else {
+ StringBuilder sb = new StringBuilder ();
+ sb.Append (method.DeclaringType.FullName);
+ sb.Append (".");
+ sb.Append (method.Name);
+ sb.Append ("(");
+ for (int i = 0; i < parameters.Length; i++) {
+ if (i > 0)
+ sb.Append (",");
+ sb.Append (parameters [i].ParameterType.FullName);
+ }
+ sb.Append (")");
+ full_name = sb.ToString ();
}
- sb.Append (")");
name = method.Name;
- full_name = sb.ToString ();
-
+
NumParameters = parameters.Length;
ParamTypeIndices = new int [NumParameters];
for (int i = 0; i < NumParameters; i++)
NumLocals = locals.Length;
Locals = locals;
- LocalTypeIndices = new int [NumLocals];
- for (int i = 0; i < NumLocals; i++)
- LocalTypeIndices [i] = file.GetNextTypeIndex ();
-
- if (method.IsStatic)
- ThisTypeIndex = 0;
- else
- ThisTypeIndex = file.DefineType (method.ReflectedType);
- }
-
- LineNumberEntry[] BuildLineNumberTable (LineNumberEntry[] line_numbers)
- {
- // Array.Sort (line_numbers, LineNumberEntry.OffsetComparer);
-
- ArrayList list = new ArrayList ();
- int last_offset = -1;
- int last_row = -1;
-
- for (int i = 0; i < line_numbers.Length; i++) {
- LineNumberEntry line = (LineNumberEntry) line_numbers [i];
-
- if (line.Offset > last_offset) {
- if (last_row >= 0)
- list.Add (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 (NumLocals <= 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 ++) {
+ string nm = locals [i].Name;
+
+ for (int j = i + 1; j < NumLocals; j ++) {
+ if (locals [j].Name == nm) {
+ LocalNamesAmbiguous = true;
+ goto locals_check_done;
+ }
+ }
+ }
+ locals_check_done :
+ ;
+ } else {
+ Hashtable local_names = new Hashtable ();
+ foreach (LocalVariableEntry local in locals) {
+ if (local_names.Contains (local.Name)) {
+ LocalNamesAmbiguous = true;
+ break;
+ }
+ local_names.Add (local.Name, local);
}
}
- if (last_row >= 0)
- list.Add (new LineNumberEntry (last_row, last_offset));
+ LocalTypeIndices = new int [NumLocals];
+ for (int i = 0; i < NumLocals; i++)
+ LocalTypeIndices [i] = file.GetNextTypeIndex ();
- LineNumberEntry[] retval = new LineNumberEntry [list.Count];
- list.CopyTo (retval, 0);
- return retval;
+ ClassTypeIndex = file.DefineType (method.ReflectedType);
}
internal MethodSourceEntry Write (MonoSymbolFile file, BinaryWriter bw)
bw.Write (LocalTypeIndices [i]);
LocalVariableTableOffset = (int) bw.BaseStream.Position;
-
for (int i = 0; i < NumLocals; i++)
Locals [i].Write (file, bw);
+ file.LocalCount += NumLocals;
LineNumberTableOffset = (int) bw.BaseStream.Position;
-
for (int i = 0; i < NumLineNumbers; i++)
LineNumbers [i].Write (bw);
-
file.LineNumberCount += NumLineNumbers;
- file.LocalCount += NumLocals;
+ LexicalBlockTableOffset = (int) bw.BaseStream.Position;
+ for (int i = 0; i < NumLexicalBlocks; i++)
+ LexicalBlocks [i].Write (bw);
file_offset = (int) bw.BaseStream.Position;
+ index_entry = new MethodIndexEntry (file_offset, FullNameOffset, Token);
+
bw.Write (SourceFileIndex);
bw.Write (Token);
bw.Write (StartRow);
bw.Write (EndRow);
- bw.Write (ThisTypeIndex);
+ bw.Write (ClassTypeIndex);
bw.Write (NumParameters);
bw.Write (NumLocals);
bw.Write (NumLineNumbers);
bw.Write (TypeIndexTableOffset);
bw.Write (LocalVariableTableOffset);
bw.Write (LineNumberTableOffset);
+ bw.Write (NumLexicalBlocks);
+ bw.Write (LexicalBlockTableOffset);
+ bw.Write (NamespaceID);
+ bw.Write (LocalNamesAmbiguous ? 1 : 0);
- return new MethodSourceEntry (index, file_offset, StartRow, EndRow);
+ return new MethodSourceEntry (Index, file_offset, StartRow, EndRow);
}
internal void WriteIndex (BinaryWriter bw)
{
- bw.Write (file_offset);
- bw.Write (FullNameOffset);
+ index_entry.Write (bw);
}
public override string ToString ()
{
return String.Format ("[Method {0}:{1}:{2}:{3}:{4} - {7}:{8}:{9}:{10} - {5} - {6}]",
- index, Token, SourceFileIndex, StartRow, EndRow,
- SourceFile, FullName, ThisTypeIndex, NumParameters,
+ Index, Token, SourceFileIndex, StartRow, EndRow,
+ SourceFile, FullName, ClassTypeIndex, NumParameters,
NumLocals, NumLineNumbers);
}
}
+
+ public struct NamespaceEntry
+ {
+ public readonly string Name;
+ public readonly int Index;
+ public readonly int Parent;
+ public readonly string[] UsingClauses;
+
+ public NamespaceEntry (string name, int index, string[] using_clauses, int parent)
+ {
+ this.Name = name;
+ this.Index = index;
+ this.Parent = parent;
+ this.UsingClauses = using_clauses != null ? using_clauses : new string [0];
+ }
+
+ internal void Write (MonoSymbolFile file, BinaryWriter bw)
+ {
+ file.WriteString (bw, Name);
+ bw.Write (Index);
+ bw.Write (Parent);
+ bw.Write (UsingClauses.Length);
+ foreach (string uc in UsingClauses)
+ file.WriteString (bw, uc);
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("[Namespace {0}:{1}:{2}]", Name, Index, Parent);
+ }
+ }
}