//
-// System.Diagnostics.SymbolStore/MonoSymbolFile.cs
+// Mono.CSharp.Debugger/MonoSymbolFile.cs
//
// Author:
-// Martin Baulig (martin@gnome.org)
+// Martin Baulig (martin@ximian.com)
//
// (C) 2003 Ximian, Inc. http://www.ximian.com
//
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
using System;
using System.Reflection;
-using System.Reflection.Emit;
using System.Collections;
using System.Text;
+using System.Threading;
using System.IO;
-namespace Mono.CSharp.Debugger
+namespace Mono.CompilerServices.SymbolWriter
{
public class MonoSymbolFileException : Exception
{
}
}
+ internal class MyBinaryWriter : BinaryWriter
+ {
+ public MyBinaryWriter (Stream stream)
+ : base (stream)
+ { }
+
+ public void WriteLeb128 (int value)
+ {
+ base.Write7BitEncodedInt (value);
+ }
+ }
+
+ internal class MyBinaryReader : BinaryReader
+ {
+ public MyBinaryReader (Stream stream)
+ : base (stream)
+ { }
+
+ public int ReadLeb128 ()
+ {
+ return base.Read7BitEncodedInt ();
+ }
+ }
+
public class MonoDebuggerSupport
{
- static MethodInfo get_token;
- static MethodInfo get_method_token;
- static MethodInfo get_method;
- static MethodInfo local_type_from_sig;
+ static GetTypeFunc get_type;
+ static GetMethodTokenFunc get_method_token;
+ static GetMethodFunc get_method;
+ static GetLocalTypeFromSignatureFunc local_type_from_sig;
+ static GetGuidFunc get_guid;
+ static CheckRuntimeVersionFunc check_runtime_version;
+
+ 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);
+ delegate Guid GetGuidFunc (Module module);
+ delegate string CheckRuntimeVersionFunc (string filename);
+
+ static Delegate create_delegate (Type type, Type delegate_type, string name)
+ {
+ 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 ()
{
- Type type = typeof (Assembly);
- get_method_token = type.GetMethod ("MonoDebugger_GetMethodToken",
- BindingFlags.Instance |
- BindingFlags.NonPublic);
- if (get_method_token == null)
- throw new Exception (
- "Can't find Assembly.MonoDebugger_GetMethodToken");
-
- get_method = type.GetMethod ("MonoDebugger_GetMethod",
- BindingFlags.Instance |
- BindingFlags.NonPublic);
- if (get_method == null)
- throw new Exception (
- "Can't find Assembly.MonoDebugger_GetMethod");
-
- local_type_from_sig = type.GetMethod (
- "MonoDebugger_GetLocalTypeFromSignature",
- BindingFlags.Instance | BindingFlags.NonPublic);
- if (local_type_from_sig == null)
- throw new Exception (
- "Can't find Assembly.MonoDebugger_GetLocalTypeFromSignature");
+ get_type = (GetTypeFunc) create_delegate (
+ typeof (Assembly), typeof (GetTypeFunc),
+ "MonoDebugger_GetType");
+
+ get_method_token = (GetMethodTokenFunc) create_delegate (
+ typeof (Assembly), typeof (GetMethodTokenFunc),
+ "MonoDebugger_GetMethodToken");
+
+ get_method = (GetMethodFunc) create_delegate (
+ typeof (Assembly), typeof (GetMethodFunc),
+ "MonoDebugger_GetMethod");
+
+ local_type_from_sig = (GetLocalTypeFromSignatureFunc) create_delegate (
+ typeof (Assembly), typeof (GetLocalTypeFromSignatureFunc),
+ "MonoDebugger_GetLocalTypeFromSignature");
+
+ get_guid = (GetGuidFunc) create_delegate (
+ typeof (Module), typeof (GetGuidFunc), "Mono_GetGuid");
+
+ check_runtime_version = (CheckRuntimeVersionFunc) create_delegate (
+ typeof (Assembly), typeof (CheckRuntimeVersionFunc),
+ "MonoDebugger_CheckRuntimeVersion");
+ }
+
+ public static Type GetType (Assembly assembly, int token)
+ {
+ return get_type (assembly, token);
}
public static int GetMethodToken (MethodBase method)
{
- object[] args = new object[] { method };
- return (int) get_method_token.Invoke (method.ReflectedType.Assembly, args);
+ return get_method_token (method.ReflectedType.Assembly, method);
}
public static MethodBase GetMethod (Assembly assembly, int token)
{
- object[] args = new object[] { token };
- return (MethodBase) get_method.Invoke (assembly, args);
+ return get_method (assembly, token);
}
public static Type GetLocalTypeFromSignature (Assembly assembly, byte[] sig)
{
- object[] args = new object[] { sig };
- return (Type) local_type_from_sig.Invoke (assembly, args);
+ return local_type_from_sig (assembly, sig);
+ }
+
+ public static string CheckRuntimeVersion (string filename)
+ {
+ return check_runtime_version (filename);
+ }
+
+ public static Guid GetGuid (Module module)
+ {
+ return get_guid (module);
}
}
int last_source_index;
int last_namespace_index;
+ public int NumLineNumbers;
+
public MonoSymbolFile ()
{ }
int maxCharsPerRound;
static Encoding enc = Encoding.UTF8;
- internal void WriteString (BinaryWriter bw, string s)
- {
- 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)
{
int old_pos = (int) reader.BaseStream.Position;
reader.BaseStream.Position = offset;
- int length = reader.ReadInt32 ();
- byte[] data = reader.ReadBytes (length);
- string text = Encoding.UTF8.GetString (data);
+ string text = reader.ReadString ();
+
reader.BaseStream.Position = old_pos;
return text;
}
- void Write (BinaryWriter bw)
+ void Write (MyBinaryWriter bw, Guid guid)
{
// Magic number and file version.
bw.Write (OffsetTable.Magic);
bw.Write (OffsetTable.Version);
+ bw.Write (guid.ToByteArray ());
+
//
// Offsets of file sections; we must write this after we're done
// writing the whole file, so we just reserve the space for it here.
long offset_table_offset = bw.BaseStream.Position;
ot.Write (bw);
+ //
+ // Sort the methods according to their tokens and update their index.
+ //
+ methods.Sort ();
+ for (int i = 0; i < methods.Count; i++)
+ ((MethodEntry) methods [i]).Index = i + 1;
+
//
// Write data sections.
//
ot.DataSectionSize = (int) bw.BaseStream.Position - ot.DataSectionOffset;
//
- // Write method table.
+ // Write the method index table.
//
ot.MethodTableOffset = (int) bw.BaseStream.Position;
for (int i = 0; i < methods.Count; i++) {
bw.Seek (0, SeekOrigin.End);
}
- public byte[] CreateSymbolFile ()
+ public byte[] CreateSymbolFile (Guid guid)
{
if (reader != null)
throw new InvalidOperationException ();
using (MyMemoryStream stream = new MyMemoryStream ()) {
- Write (new BinaryWriter (stream));
+ Write (new MyBinaryWriter (stream), guid);
return stream.GetContents ();
}
}
Assembly assembly;
- BinaryReader reader;
+ MyBinaryReader reader;
Hashtable method_hash;
Hashtable source_file_hash;
Hashtable method_token_hash;
- Hashtable method_name_hash;
- Hashtable method_full_name_hash;
Hashtable source_name_hash;
- protected MonoSymbolFile (Assembly assembly, Stream stream)
+ protected MonoSymbolFile (string filename, Assembly assembly)
{
this.assembly = assembly;
- reader = new BinaryReader (stream);
+ FileStream stream = new FileStream (filename, FileMode.Open, FileAccess.Read);
+ reader = new MyBinaryReader (stream);
+
+ Guid guid;
try {
long magic = reader.ReadInt64 ();
long version = reader.ReadInt32 ();
- if ((magic != OffsetTable.Magic) || (version != OffsetTable.Version))
- throw new MonoSymbolFileException ();
+ if (magic != OffsetTable.Magic)
+ throw new MonoSymbolFileException (
+ "Symbol file `{0}' is not a valid " +
+ "Mono symbol file", filename);
+ if (version != OffsetTable.Version)
+ throw new MonoSymbolFileException (
+ "Symbol file `{0}' has version {1}, " +
+ "but expected {2}", filename, version,
+ OffsetTable.Version);
+
+ guid = new Guid (reader.ReadBytes (16));
+
ot = new OffsetTable (reader);
} catch {
- throw new MonoSymbolFileException ();
+ throw new MonoSymbolFileException (
+ "Cannot read symbol file `{0}'", filename);
}
+ Module[] modules = assembly.GetModules ();
+ Guid assembly_guid = MonoDebuggerSupport.GetGuid (modules [0]);
+
+ if (guid != assembly_guid)
+ throw new MonoSymbolFileException (
+ "Symbol file `{0}' does not match assembly `{1}'",
+ filename, assembly.Location);
+
method_hash = new Hashtable ();
source_file_hash = new Hashtable ();
}
public static MonoSymbolFile ReadSymbolFile (Assembly assembly)
{
- Stream stream = assembly.GetManifestResourceStream ("MonoSymbolFile");
- if (stream == null)
- return null;
+ string filename = assembly.Location;
+ string name = filename + ".mdb";
- return new MonoSymbolFile (assembly, stream);
+ return new MonoSymbolFile (name, assembly);
}
public Assembly Assembly {
throw new MonoSymbolFileException ("Internal error.");
}
- public int FindMethod (string full_name)
- {
- if (reader == null)
- throw new InvalidOperationException ();
-
- if (method_full_name_hash == null) {
- method_full_name_hash = new Hashtable ();
-
- for (int i = 0; i < ot.MethodCount; i++) {
- MethodIndexEntry ie = GetMethodIndexEntry (i + 1);
- string name = ReadString (ie.FullNameOffset);
-
- method_full_name_hash.Add (name, i + 1);
- }
- }
-
- object value = method_full_name_hash [full_name];
- if (value == null)
- return -1;
- return (int) value;
- }
-
- public int[] MethodLookup (string query)
- {
- if (reader == null)
- throw new InvalidOperationException ();
-
- ArrayList list;
- if (method_name_hash == null) {
- method_name_hash = new Hashtable ();
-
- for (int i = 0; i < ot.MethodCount; i++) {
- MethodIndexEntry ie = GetMethodIndexEntry (i + 1);
- string full_name = ReadString (ie.FullNameOffset);
-
- int pos = full_name.IndexOf ('(');
- string name = full_name.Substring (0, pos);
-
- list = method_name_hash [name] as ArrayList;
- if (list == null) {
- list = new ArrayList ();
- method_name_hash.Add (name, list);
- }
-
- list.Add (i + 1);
- }
- }
-
- list = method_name_hash [query] as ArrayList;
- if (list == null)
- return new int [0];
-
- int[] retval = new int [list.Count];
- list.CopyTo (retval, 0);
- return retval;
- }
-
public int FindSource (string file_name)
{
if (reader == null)
return (int) value;
}
- internal BinaryReader BinaryReader {
+ internal MyBinaryReader BinaryReader {
get {
if (reader == null)
throw new InvalidOperationException ();