{ }
}
+ internal class MyMemoryStream : Stream
+ {
+ int length;
+ int real_length;
+ int position;
+
+ int chunk_size = 4096;
+ ArrayList chunks = new ArrayList ();
+
+ private struct Chunk {
+ public readonly int Offset;
+ public readonly int Length;
+ public byte[] Buffer;
+
+ public Chunk (int offset, int length)
+ {
+ this.Offset = offset;
+ this.Length = length;
+ this.Buffer = new Byte [length];
+ }
+ }
+
+ public override long Position {
+ get { return position; }
+
+ set {
+ if (value > length)
+ throw new ArgumentOutOfRangeException ();
+
+ position = (int) value;
+ }
+ }
+
+ public override long Length {
+ get { return length; }
+ }
+
+ public override bool CanRead {
+ get { return true; }
+ }
+
+ public override bool CanWrite {
+ get { return true; }
+ }
+
+ public override bool CanSeek {
+ get { return true; }
+ }
+
+ public override void SetLength (long new_length)
+ {
+ if (new_length < length)
+ throw new ArgumentException ();
+
+ while (new_length >= real_length) {
+ Chunk new_chunk = new Chunk (real_length, chunk_size);
+ chunks.Add (new_chunk);
+ real_length += chunk_size;
+ }
+
+ length = (int) new_length;
+ }
+
+ public override void Flush ()
+ { }
+
+ public override long Seek (long offset, SeekOrigin origin)
+ {
+ int ref_point;
+
+ switch (origin) {
+ case SeekOrigin.Begin:
+ ref_point = 0;
+ break;
+ case SeekOrigin.Current:
+ ref_point = position;
+ break;
+ case SeekOrigin.End:
+ ref_point = length;
+ break;
+ default:
+ throw new ArgumentException ("Invalid SeekOrigin");
+ }
+
+ if ((ref_point + offset < 0) || (offset > real_length))
+ throw new ArgumentOutOfRangeException ();
+
+ position = ref_point + (int) offset;
+
+ return position;
+ }
+
+ Chunk FindChunk (int offset)
+ {
+ return (Chunk) chunks [offset / chunk_size];
+ }
+
+ public override int Read (byte[] buffer, int offset, int count)
+ {
+ int old_count = count;
+
+ while (count > 0) {
+ Chunk chunk = FindChunk (position);
+ int coffset = position - chunk.Offset;
+ int rest = chunk.Length - coffset;
+ int size = System.Math.Min (count, rest);
+
+ Array.Copy (chunk.Buffer, coffset, buffer, offset, size);
+ position += size;
+ offset += size;
+ count -= size;
+ }
+
+ return old_count;
+ }
+
+ public override void Write (byte[] buffer, int offset, int count)
+ {
+ if (position + count > length)
+ SetLength (position + count);
+
+ while (count > 0) {
+ Chunk chunk = FindChunk (position);
+ int coffset = position - chunk.Offset;
+ int rest = chunk.Length - coffset;
+ int size = System.Math.Min (count, rest);
+
+ Array.Copy (buffer, offset, chunk.Buffer, coffset, size);
+ position += size;
+ offset += size;
+ count -= size;
+ }
+ }
+
+ public byte[] GetContents ()
+ {
+ byte[] retval = new byte [length];
+ position = 0;
+ Read (retval, 0, length);
+ return retval;
+ }
+ }
+
+ 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)
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);
+ 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)
bw.Seek (0, SeekOrigin.End);
}
- public void WriteSymbolFile (string output_filename)
+ public byte[] CreateSymbolFile ()
{
if (reader != null)
throw new InvalidOperationException ();
- using (FileStream stream = new FileStream (output_filename, FileMode.Create))
+ using (MyMemoryStream stream = new MyMemoryStream ()) {
Write (new BinaryWriter (stream));
+ return stream.GetContents ();
+ }
}
- FileStream stream;
+ Assembly assembly;
BinaryReader reader;
Hashtable method_hash;
Hashtable source_file_hash;
- Hashtable method_name_hash;
+ Hashtable method_token_hash;
Hashtable source_name_hash;
- public MonoSymbolFile (string file_name)
+ protected MonoSymbolFile (Assembly assembly, Stream stream)
{
- stream = File.OpenRead (file_name);
+ this.assembly = assembly;
+
reader = new BinaryReader (stream);
try {
source_file_hash = new Hashtable ();
}
+ public static MonoSymbolFile ReadSymbolFile (Assembly assembly)
+ {
+ Stream stream = assembly.GetManifestResourceStream ("MonoSymbolFile");
+ if (stream == null)
+ return null;
+
+ return new MonoSymbolFile (assembly, stream);
+ }
+
+ public Assembly Assembly {
+ get { return assembly; }
+ }
+
public int SourceCount {
get { return ot.SourceCount; }
}
get { return ot.TypeCount; }
}
+ public int NamespaceCount {
+ get { return last_namespace_index; }
+ }
+
+ internal int LineNumberCount = 0;
+ internal int LocalCount = 0;
+ internal int StringSize = 0;
+
public SourceFileEntry GetSourceFile (int index)
{
if ((index < 1) || (index > ot.SourceCount))
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))
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)
protected virtual void Dispose (bool disposing)
{
if (disposing) {
- if (stream != null) {
- stream.Close ();
- stream = null;
- }
if (reader != null) {
reader.Close ();
reader = null;