2004-04-30 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / Mono.CSharp.Debugger / MonoSymbolFile.cs
index 5afac4d782e31f149bbf0b8600b45dfa1c23ec4b..e0befd743bf519a6cce4634f6dbf6567944848a3 100644 (file)
@@ -132,7 +132,7 @@ namespace Mono.CSharp.Debugger
                                Chunk chunk = FindChunk (position);
                                int coffset = position - chunk.Offset;
                                int rest = chunk.Length - coffset;
-                               int size = Math.Min (count, rest);
+                               int size = System.Math.Min (count, rest);
 
                                Array.Copy (chunk.Buffer, coffset, buffer, offset, size);
                                position += size;
@@ -152,7 +152,7 @@ namespace Mono.CSharp.Debugger
                                Chunk chunk = FindChunk (position);
                                int coffset = position - chunk.Offset;
                                int rest = chunk.Length - coffset;
-                               int size = Math.Min (count, rest);
+                               int size = System.Math.Min (count, rest);
 
                                Array.Copy (buffer, offset, chunk.Buffer, coffset, size);
                                position += size;
@@ -170,32 +170,87 @@ namespace Mono.CSharp.Debugger
                }
        }
 
+       public class MonoDebuggerSupport
+       {
+               static GetTypeFunc get_type;
+               static GetMethodTokenFunc get_method_token;
+               static GetMethodFunc get_method;
+               static GetLocalTypeFromSignatureFunc local_type_from_sig;
+
+               delegate Type GetTypeFunc (Assembly assembly, int token);
+               delegate int GetMethodTokenFunc (Assembly assembly, MethodBase method);
+               delegate MethodBase GetMethodFunc (Assembly assembly, int token);
+               delegate Type GetLocalTypeFromSignatureFunc (Assembly assembly, byte[] sig);
+
+               static Delegate create_delegate (Type delegate_type, string name)
+               {
+                       Type type = typeof (Assembly);
+
+                       MethodInfo mi = type.GetMethod (name, BindingFlags.Static |
+                                                       BindingFlags.NonPublic);
+                       if (mi == null)
+                               throw new Exception ("Can't find " + name);
+
+                       return Delegate.CreateDelegate (delegate_type, mi);
+               }
+
+               static MonoDebuggerSupport ()
+               {
+                       get_type = (GetTypeFunc) create_delegate (
+                               typeof (GetTypeFunc), "MonoDebugger_GetType");
+
+                       get_method_token = (GetMethodTokenFunc) create_delegate (
+                               typeof (GetMethodTokenFunc), "MonoDebugger_GetMethodToken");
+
+                       get_method = (GetMethodFunc) create_delegate (
+                               typeof (GetMethodFunc), "MonoDebugger_GetMethod");
+
+                       local_type_from_sig = (GetLocalTypeFromSignatureFunc) create_delegate (
+                               typeof (GetLocalTypeFromSignatureFunc),
+                               "MonoDebugger_GetLocalTypeFromSignature");
+               }
+
+               public static Type GetType (Assembly assembly, int token)
+               {
+                       return get_type (assembly, token);
+               }
+
+               public static int GetMethodToken (MethodBase method)
+               {
+                       return get_method_token (method.ReflectedType.Assembly, method);
+               }
+
+               public static MethodBase GetMethod (Assembly assembly, int token)
+               {
+                       return get_method (assembly, token);
+               }
+
+               public static Type GetLocalTypeFromSignature (Assembly assembly, byte[] sig)
+               {
+                       return local_type_from_sig (assembly, sig);
+               }
+       }
+
        public class MonoSymbolFile : IDisposable
        {
                ArrayList methods = new ArrayList ();
                ArrayList sources = new ArrayList ();
-               Hashtable source_hash = new Hashtable ();
+               Hashtable method_source_hash = new Hashtable ();
                Hashtable type_hash = new Hashtable ();
 
                OffsetTable ot;
                int last_type_index;
                int last_method_index;
+               int last_source_index;
+               int last_namespace_index;
 
                public MonoSymbolFile ()
                { }
 
-               public SourceFileEntry DefineSource (string source_file)
+               internal int AddSource (SourceFileEntry source)
                {
-                       if (reader != null)
-                               throw new InvalidOperationException ();
-
-                       SourceFileEntry source = (SourceFileEntry) source_hash [source_file];
-                       if (source == null) {
-                               source = new SourceFileEntry (this, source_file, sources.Count + 1);
-                               source_hash.Add (source_file, source);
-                               sources.Add (source);
-                       }
-                       return source;
+                       sources.Add (source);
+                       return ++last_source_index;
                }
 
                internal int DefineType (Type type)
@@ -223,12 +278,36 @@ namespace Mono.CSharp.Debugger
                        return ++last_method_index;
                }
 
-               internal void WriteString (BinaryWriter bw, string text)
+               internal int GetNextNamespaceIndex ()
+               {
+                       return ++last_namespace_index;
+               }
+
+               byte [] stringBuffer;
+               int maxCharsPerRound;
+               static Encoding enc = Encoding.UTF8;
+               
+               internal void WriteString (BinaryWriter bw, string s)
                {
-                       byte[] data = Encoding.UTF8.GetBytes (text);
-                       bw.Write ((int) data.Length);
-                       bw.Write (data);
-                       StringSize += data.Length;
+                       int len = enc.GetByteCount (s);
+                       bw.Write (len);
+                       StringSize += len;
+                       
+                       if (stringBuffer == null) {
+                               stringBuffer = new byte [512];
+                               maxCharsPerRound = 512 / enc.GetMaxByteCount (1);
+                       }
+                       
+                       int chpos = 0;
+                       int chrem = s.Length;
+                       while (chrem > 0) {
+                               int cch = (chrem > maxCharsPerRound) ? maxCharsPerRound : chrem;
+                               int blen = enc.GetBytes (s, chpos, cch, stringBuffer, 0);
+                               bw.Write (stringBuffer, 0, blen);
+                               
+                               chpos += cch;
+                               chrem -= cch;
+                       }
                }
 
                internal string ReadString (int offset)
@@ -307,25 +386,22 @@ namespace Mono.CSharp.Debugger
 
                        using (MyMemoryStream stream = new MyMemoryStream ()) {
                                Write (new BinaryWriter (stream));
-                               Console.WriteLine ("WROTE SYMFILE: {0} sources, {1} methods, {2} types, " +
-                                                  "{3} line numbers, {4} locals, {5} bytes of string data",
-                                                  SourceCount, MethodCount, TypeCount, LineNumberCount,
-                                                  LocalCount, StringSize);
-                               Console.WriteLine (ot);
                                return stream.GetContents ();
                        }
                }
 
-               // Stream stream;
+               Assembly assembly;
                BinaryReader reader;
                Hashtable method_hash;
                Hashtable source_file_hash;
 
-               Hashtable method_name_hash;
+               Hashtable method_token_hash;
                Hashtable source_name_hash;
 
-               protected MonoSymbolFile (Stream stream)
+               protected MonoSymbolFile (Assembly assembly, Stream stream)
                {
+                       this.assembly = assembly;
+
                        reader = new BinaryReader (stream);
 
                        try {
@@ -348,7 +424,11 @@ namespace Mono.CSharp.Debugger
                        if (stream == null)
                                return null;
 
-                       return new MonoSymbolFile (stream);
+                       return new MonoSymbolFile (assembly, stream);
+               }
+
+               public Assembly Assembly {
+                       get { return assembly; }
                }
 
                public int SourceCount {
@@ -363,6 +443,10 @@ namespace Mono.CSharp.Debugger
                        get { return ot.TypeCount; }
                }
 
+               public int NamespaceCount {
+                       get { return last_namespace_index; }
+               }
+
                internal int LineNumberCount = 0;
                internal int LocalCount = 0;
                internal int StringSize = 0;
@@ -385,6 +469,58 @@ namespace Mono.CSharp.Debugger
                        return source;
                }
 
+               public SourceFileEntry[] Sources {
+                       get {
+                               if (reader == null)
+                                       throw new InvalidOperationException ();
+
+                               SourceFileEntry[] retval = new SourceFileEntry [SourceCount];
+                               for (int i = 0; i < SourceCount; i++)
+                                       retval [i] = GetSourceFile (i + 1);
+                               return retval;
+                       }
+               }
+
+               public MethodIndexEntry GetMethodIndexEntry (int index)
+               {
+                       int old_pos = (int) reader.BaseStream.Position;
+                       reader.BaseStream.Position = ot.MethodTableOffset +
+                               MethodIndexEntry.Size * (index - 1);
+                       MethodIndexEntry ie = new MethodIndexEntry (reader);
+                       reader.BaseStream.Position = old_pos;
+                       return ie;
+               }
+
+               public MethodEntry GetMethodByToken (int token)
+               {
+                       if (reader == null)
+                               throw new InvalidOperationException ();
+
+                       if (method_token_hash == null) {
+                               method_token_hash = new Hashtable ();
+
+                               for (int i = 0; i < MethodCount; i++) {
+                                       MethodIndexEntry ie = GetMethodIndexEntry (i + 1);
+
+                                       method_token_hash.Add (ie.Token, i + 1);
+                               }
+                       }
+
+                       object value = method_token_hash [token];
+                       if (value == null)
+                               return null;
+
+                       return GetMethod ((int) value);
+               }
+
+               public MethodEntry GetMethod (MethodBase method)
+               {
+                       if (reader == null)
+                               throw new InvalidOperationException ();
+                       int token = MonoDebuggerSupport.GetMethodToken (method);
+                       return GetMethodByToken (token);
+               }
+
                public MethodEntry GetMethod (int index)
                {
                        if ((index < 1) || (index > ot.MethodCount))
@@ -396,37 +532,46 @@ namespace Mono.CSharp.Debugger
                        if (entry != null)
                                return entry;
 
-                       reader.BaseStream.Position = ot.MethodTableOffset + 8 * (index - 1);
-                       reader.BaseStream.Position = reader.ReadInt32 ();
+                       MethodIndexEntry ie = GetMethodIndexEntry (index);
+                       reader.BaseStream.Position = ie.FileOffset;
 
-                       entry = new MethodEntry (this, reader);
+                       entry = new MethodEntry (this, reader, index);
                        method_hash.Add (index, entry);
                        return entry;
                }
 
-               public int FindMethod (string full_name)
+               public MethodEntry[] Methods {
+                       get {
+                               if (reader == null)
+                                       throw new InvalidOperationException ();
+
+                               MethodEntry[] retval = new MethodEntry [MethodCount];
+                               for (int i = 0; i < MethodCount; i++)
+                                       retval [i] = GetMethod (i + 1);
+                               return retval;
+                       }
+               }
+
+               public MethodSourceEntry GetMethodSource (int index)
                {
+                       if ((index < 1) || (index > ot.MethodCount))
+                               throw new ArgumentException ();
                        if (reader == null)
                                throw new InvalidOperationException ();
 
-                       if (method_name_hash == null) {
-                               method_name_hash = new Hashtable ();
-
-                               for (int i = 0; i < ot.MethodCount; i++) {
-                                       reader.BaseStream.Position = ot.MethodTableOffset + 8 * i;
-
-                                       int offset = reader.ReadInt32 ();
-                                       int name_offset = reader.ReadInt32 ();
-                                       string name = ReadString (name_offset);
+                       object entry = method_source_hash [index];
+                       if (entry != null)
+                               return (MethodSourceEntry) entry;
 
-                                       method_name_hash.Add (name, i);
+                       MethodEntry method = GetMethod (index);
+                       foreach (MethodSourceEntry source in method.SourceFile.Methods) {
+                               if (source.Index == index) {
+                                       method_source_hash.Add (index, source);
+                                       return source;
                                }
                        }
 
-                       object value = method_name_hash [full_name];
-                       if (value == null)
-                               return -1;
-                       return (int) value;
+                       throw new MonoSymbolFileException ("Internal error.");
                }
 
                public int FindSource (string file_name)