Always call SSPIWrapper.CheckRemoteCertificate().
[mono.git] / mcs / class / Mono.CompilerServices.SymbolWriter / MonoSymbolFile.cs
index ec7030ff71eeacbc6e6f8573e50dbd333d3d5cea..8431c70a4548e27b9ea3c6be7b7a0ddd667ac42f 100644 (file)
@@ -1,12 +1,13 @@
 //
-// Mono.CSharp.Debugger/MonoSymbolFile.cs
+// MonoSymbolFile.cs
 //
-// Author:
+// Authors:
 //   Martin Baulig (martin@ximian.com)
+//   Marek Safar (marek.safar@gmail.com)
 //
 // (C) 2003 Ximian, Inc.  http://www.ximian.com
+// Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
 //
-
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 
 using System;
 using System.Reflection;
-using SRE = System.Reflection.Emit;
-using System.Collections;
-using System.Text;
-using System.Threading;
+using System.Collections.Generic;
 using System.IO;
        
 namespace Mono.CompilerServices.SymbolWriter
@@ -46,10 +44,16 @@ namespace Mono.CompilerServices.SymbolWriter
 
                public MonoSymbolFileException (string message, params object[] args)
                        : base (String.Format (message, args))
-               { }
+               {
+               }
+
+               public MonoSymbolFileException (string message, Exception innerException)
+                       : base (message, innerException)
+               {
+               }
        }
 
-       internal class MyBinaryWriter : BinaryWriter
+       sealed class MyBinaryWriter : BinaryWriter
        {
                public MyBinaryWriter (Stream stream)
                        : base (stream)
@@ -71,106 +75,106 @@ namespace Mono.CompilerServices.SymbolWriter
                {
                        return base.Read7BitEncodedInt ();
                }
-       }
-
-#if !CECIL
-       internal class MonoDebuggerSupport
-       {
-               static GetMethodTokenFunc get_method_token;
-               static GetGuidFunc get_guid;
-               static GetLocalIndexFunc get_local_index;
-
-               delegate int GetMethodTokenFunc (MethodBase method);
-               delegate Guid GetGuidFunc (Module module);
-               delegate int GetLocalIndexFunc (SRE.LocalBuilder local);
 
-               static Delegate create_delegate (Type type, Type delegate_type, string name)
+               public string ReadString (int offset)
                {
-                       MethodInfo mi = type.GetMethod (name, BindingFlags.Static |
-                                                       BindingFlags.NonPublic);
-                       if (mi == null)
-                               throw new Exception ("Can't find " + name);
+                       long old_pos = BaseStream.Position;
+                       BaseStream.Position = offset;
 
-                       return Delegate.CreateDelegate (delegate_type, mi);
-               }
-
-               static MonoDebuggerSupport ()
-               {
-                       get_method_token = (GetMethodTokenFunc) create_delegate (
-                               typeof (Assembly), typeof (GetMethodTokenFunc),
-                               "MonoDebugger_GetMethodToken");
+                       string text = ReadString ();
 
-                       get_guid = (GetGuidFunc) create_delegate (
-                               typeof (Module), typeof (GetGuidFunc), "Mono_GetGuid");
+                       BaseStream.Position = old_pos;
+                       return text;
+               }
+       }
 
-                       get_local_index = (GetLocalIndexFunc) create_delegate (
-                               typeof (SRE.LocalBuilder), typeof (GetLocalIndexFunc),
-                               "Mono_GetLocalIndex");
+       public interface ISourceFile
+       {
+               SourceFileEntry Entry {
+                       get;
                }
+       }
 
-               public static int GetMethodToken (MethodBase method)
-               {
-                       return get_method_token (method);
+       public interface ICompileUnit
+       {
+               CompileUnitEntry Entry {
+                       get;
                }
+       }
 
-               public static Guid GetGuid (Module module)
-               {
-                       return get_guid (module);
+       public interface IMethodDef
+       {
+               string Name {
+                       get;
                }
 
-               public static int GetLocalIndex (SRE.LocalBuilder local)
-               {
-                       return get_local_index (local);
+               int Token {
+                       get;
                }
        }
-#endif
 
        public class MonoSymbolFile : IDisposable
        {
-               ArrayList methods = new ArrayList ();
-               ArrayList sources = new ArrayList ();
-               Hashtable method_source_hash = new Hashtable ();
-               Hashtable type_hash = new Hashtable ();
-               Hashtable anonymous_scopes;
+               List<MethodEntry> methods = new List<MethodEntry> ();
+               List<SourceFileEntry> sources = new List<SourceFileEntry> ();
+               List<CompileUnitEntry> comp_units = new List<CompileUnitEntry> ();
+               Dictionary<int, AnonymousScopeEntry> anonymous_scopes;
 
                OffsetTable ot;
                int last_type_index;
                int last_method_index;
-               int last_source_index;
                int last_namespace_index;
 
-               public readonly int Version = OffsetTable.Version;
+               public readonly int MajorVersion = OffsetTable.MajorVersion;
+               public readonly int MinorVersion = OffsetTable.MinorVersion;
 
                public int NumLineNumbers;
 
                public MonoSymbolFile ()
-               { }
+               {
+                       ot = new OffsetTable ();
+               }
 
-               internal int AddSource (SourceFileEntry source)
+               public int AddSource (SourceFileEntry source)
                {
                        sources.Add (source);
-                       return ++last_source_index;
+                       return sources.Count;
                }
 
-               internal int DefineType (Type type)
+               public int AddCompileUnit (CompileUnitEntry entry)
                {
-                       if (type_hash.Contains (type))
-                               return (int) type_hash [type];
-
-                       int index = ++last_type_index;
-                       type_hash.Add (type, index);
-                       return index;
+                       comp_units.Add (entry);
+                       return comp_units.Count;
                }
 
-               internal void AddMethod (MethodEntry entry)
+               public void AddMethod (MethodEntry entry)
                {
                        methods.Add (entry);
                }
 
+               public MethodEntry DefineMethod (CompileUnitEntry comp_unit, int token,
+                                                ScopeVariable[] scope_vars, LocalVariableEntry[] locals,
+                                                LineNumberEntry[] lines, CodeBlockEntry[] code_blocks,
+                                                string real_name, MethodEntry.Flags flags,
+                                                int namespace_id)
+               {
+                       if (reader != null)
+                               throw new InvalidOperationException ();
+
+                       MethodEntry method = new MethodEntry (
+                               this, comp_unit, token, scope_vars, locals, lines, code_blocks, 
+                               real_name, flags, namespace_id);
+                       AddMethod (method);
+                       return method;
+               }
+
                internal void DefineAnonymousScope (int id)
                {
+                       if (reader != null)
+                               throw new InvalidOperationException ();
+
                        if (anonymous_scopes == null)
-                               anonymous_scopes = new Hashtable ();
+                               anonymous_scopes = new Dictionary<int, AnonymousScopeEntry>  ();
 
                        anonymous_scopes.Add (id, new AnonymousScopeEntry (id));
                }
@@ -178,13 +182,19 @@ namespace Mono.CompilerServices.SymbolWriter
                internal void DefineCapturedVariable (int scope_id, string name, string captured_name,
                                                      CapturedVariable.CapturedKind kind)
                {
-                       AnonymousScopeEntry scope = (AnonymousScopeEntry) anonymous_scopes [scope_id];
+                       if (reader != null)
+                               throw new InvalidOperationException ();
+
+                       AnonymousScopeEntry scope = anonymous_scopes [scope_id];
                        scope.AddCapturedVariable (name, captured_name, kind);
                }
 
                internal void DefineCapturedScope (int scope_id, int id, string captured_name)
                {
-                       AnonymousScopeEntry scope = (AnonymousScopeEntry) anonymous_scopes [scope_id];
+                       if (reader != null)
+                               throw new InvalidOperationException ();
+
+                       AnonymousScopeEntry scope = anonymous_scopes [scope_id];
                        scope.AddCapturedScope (id, captured_name);
                }
 
@@ -203,22 +213,12 @@ namespace Mono.CompilerServices.SymbolWriter
                        return ++last_namespace_index;
                }
                
-               internal string ReadString (int offset)
-               {
-                       int old_pos = (int) reader.BaseStream.Position;
-                       reader.BaseStream.Position = offset;
-
-                       string text = reader.ReadString ();
-
-                       reader.BaseStream.Position = old_pos;
-                       return text;
-               }
-
                void Write (MyBinaryWriter bw, Guid guid)
                {
                        // Magic number and file version.
                        bw.Write (OffsetTable.Magic);
-                       bw.Write (Version);
+                       bw.Write (MajorVersion);
+                       bw.Write (MinorVersion);
 
                        bw.Write (guid.ToByteArray ());
 
@@ -227,14 +227,14 @@ namespace Mono.CompilerServices.SymbolWriter
                        // writing the whole file, so we just reserve the space for it here.
                        //
                        long offset_table_offset = bw.BaseStream.Position;
-                       ot.Write (bw, Version);
+                       ot.Write (bw, MajorVersion, MinorVersion);
 
                        //
                        // 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;
+                               methods [i].Index = i + 1;
 
                        //
                        // Write data sections.
@@ -242,6 +242,10 @@ namespace Mono.CompilerServices.SymbolWriter
                        ot.DataSectionOffset = (int) bw.BaseStream.Position;
                        foreach (SourceFileEntry source in sources)
                                source.WriteData (bw);
+                       foreach (CompileUnitEntry comp_unit in comp_units)
+                               comp_unit.WriteData (bw);
+                       foreach (MethodEntry method in methods)
+                               method.WriteData (this, bw);
                        ot.DataSectionSize = (int) bw.BaseStream.Position - ot.DataSectionOffset;
 
                        //
@@ -249,8 +253,8 @@ namespace Mono.CompilerServices.SymbolWriter
                        //
                        ot.MethodTableOffset = (int) bw.BaseStream.Position;
                        for (int i = 0; i < methods.Count; i++) {
-                               MethodEntry entry = (MethodEntry) methods [i];
-                               entry.WriteIndex (bw);
+                               MethodEntry entry = methods [i];
+                               entry.Write (bw);
                        }
                        ot.MethodTableSize = (int) bw.BaseStream.Position - ot.MethodTableOffset;
 
@@ -259,11 +263,21 @@ namespace Mono.CompilerServices.SymbolWriter
                        //
                        ot.SourceTableOffset = (int) bw.BaseStream.Position;
                        for (int i = 0; i < sources.Count; i++) {
-                               SourceFileEntry source = (SourceFileEntry) sources [i];
+                               SourceFileEntry source = sources [i];
                                source.Write (bw);
                        }
                        ot.SourceTableSize = (int) bw.BaseStream.Position - ot.SourceTableOffset;
 
+                       //
+                       // Write compilation unit table.
+                       //
+                       ot.CompileUnitTableOffset = (int) bw.BaseStream.Position;
+                       for (int i = 0; i < comp_units.Count; i++) {
+                               CompileUnitEntry unit = comp_units [i];
+                               unit.Write (bw);
+                       }
+                       ot.CompileUnitTableSize = (int) bw.BaseStream.Position - ot.CompileUnitTableOffset;
+
                        //
                        // Write anonymous scope table.
                        //
@@ -281,114 +295,105 @@ namespace Mono.CompilerServices.SymbolWriter
                        ot.TypeCount = last_type_index;
                        ot.MethodCount = methods.Count;
                        ot.SourceCount = sources.Count;
+                       ot.CompileUnitCount = comp_units.Count;
 
                        //
                        // Write offset table.
                        //
                        ot.TotalFileSize = (int) bw.BaseStream.Position;
                        bw.Seek ((int) offset_table_offset, SeekOrigin.Begin);
-                       ot.Write (bw, Version);
+                       ot.Write (bw, MajorVersion, MinorVersion);
                        bw.Seek (0, SeekOrigin.End);
+
+#if false
+                       Console.WriteLine ("TOTAL: {0} line numbes, {1} bytes, extended {2} bytes, " +
+                                          "{3} methods.", NumLineNumbers, LineNumberSize,
+                                          ExtendedLineNumberSize, methods.Count);
+#endif
                }
 
                public void CreateSymbolFile (Guid guid, FileStream fs)
                {
                        if (reader != null)
                                throw new InvalidOperationException ();
-                       
+
                        Write (new MyBinaryWriter (fs), guid);
                }
 
                MyBinaryReader reader;
-               Hashtable method_hash;
-               Hashtable source_file_hash;
+               Dictionary<int, SourceFileEntry> source_file_hash;
+               Dictionary<int, CompileUnitEntry> compile_unit_hash;
 
-               Hashtable method_token_hash;
-               Hashtable source_name_hash;
+               List<MethodEntry> method_list;
+               Dictionary<int, MethodEntry> method_token_hash;
+               Dictionary<string, int> source_name_hash;
 
                Guid guid;
 
-               MonoSymbolFile (string filename)
+               MonoSymbolFile (Stream stream)
                {
-                       FileStream stream = new FileStream (filename, FileMode.Open, FileAccess.Read);
                        reader = new MyBinaryReader (stream);
 
                        try {
                                long magic = reader.ReadInt64 ();
-                               long version = reader.ReadInt32 ();
+                               int major_version = reader.ReadInt32 ();
+                               int minor_version = reader.ReadInt32 ();
+
                                if (magic != OffsetTable.Magic)
+                                       throw new MonoSymbolFileException ("Symbol file is not a valid");
+                               if (major_version != OffsetTable.MajorVersion)
                                        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);
-
-                               Version = (int) version;
+                                               "Symbol file has version {0} but expected {1}", major_version, OffsetTable.MajorVersion);
+                               if (minor_version != OffsetTable.MinorVersion)
+                                       throw new MonoSymbolFileException ("Symbol file has version {0}.{1} but expected {2}.{3}",
+                                               major_version, minor_version,
+                                               OffsetTable.MajorVersion, OffsetTable.MinorVersion);
+
+                               MajorVersion = major_version;
+                               MinorVersion = minor_version;
                                guid = new Guid (reader.ReadBytes (16));
 
-                               ot = new OffsetTable (reader, (int) version);
-                       } catch {
-                               throw new MonoSymbolFileException (
-                                       "Cannot read symbol file `{0}'", filename);
+                               ot = new OffsetTable (reader, major_version, minor_version);
+                       } catch (Exception e) {
+                               throw new MonoSymbolFileException ("Cannot read symbol file", e);
                        }
 
-                       method_hash = new Hashtable ();
-                       source_file_hash = new Hashtable ();
+                       source_file_hash = new Dictionary<int, SourceFileEntry> ();
+                       compile_unit_hash = new Dictionary<int, CompileUnitEntry> ();
                }
 
-               void CheckGuidMatch (Guid other, string filename, string assembly)
+               public static MonoSymbolFile ReadSymbolFile (Assembly assembly)
                {
-                       if (other == guid)
-                               return;
+                       string filename = assembly.Location;
+                       string name = filename + ".mdb";
+
+                       Module[] modules = assembly.GetModules ();
+                       Guid assembly_guid = modules[0].ModuleVersionId;
 
-                       throw new MonoSymbolFileException (
-                               "Symbol file `{0}' does not match assembly `{1}'",
-                               filename, assembly);
+                       return ReadSymbolFile (name, assembly_guid);
                }
 
-#if CECIL
-               protected MonoSymbolFile (string filename, Mono.Cecil.AssemblyDefinition assembly) : this (filename)
+               public static MonoSymbolFile ReadSymbolFile (string mdbFilename)
                {
-                       Guid mvid = assembly.MainModule.Mvid;
-
-                       CheckGuidMatch (mvid, filename, assembly.MainModule.Image.FileInformation.FullName);
+                       return ReadSymbolFile (new FileStream (mdbFilename, FileMode.Open, FileAccess.Read));
                }
 
-               public static MonoSymbolFile ReadSymbolFile (Mono.Cecil.AssemblyDefinition assembly, string filename)
+               public static MonoSymbolFile ReadSymbolFile (string mdbFilename, Guid assemblyGuid)
                {
-                       string name = filename + ".mdb";
+                       var sf = ReadSymbolFile (mdbFilename);
+                       if (assemblyGuid != sf.guid)
+                               throw new MonoSymbolFileException ("Symbol file `{0}' does not match assembly", mdbFilename);
 
-                       return new MonoSymbolFile (name, assembly);
+                       return sf;
                }
-#else
-               protected MonoSymbolFile (string filename, Assembly assembly) : this (filename)
-               {
-                       // Check that the MDB file matches the assembly, if we have been
-                       // passed an assembly.
-                       if (assembly == null)
-                               return;
-                       
-                       Module[] modules = assembly.GetModules ();
-                       Guid assembly_guid = MonoDebuggerSupport.GetGuid (modules [0]);
 
-                       CheckGuidMatch (assembly_guid, filename, assembly.Location);
-               }
-
-               public static MonoSymbolFile ReadSymbolFile (Assembly assembly)
+               public static MonoSymbolFile ReadSymbolFile (Stream stream)
                {
-                       string filename = assembly.Location;
-                       string name = filename + ".mdb";
-
-                       return new MonoSymbolFile (name, assembly);
+                       return new MonoSymbolFile (stream);
                }
-#endif
 
-               public static MonoSymbolFile ReadSymbolFile (string mdbFilename)
-               {
-                       return new MonoSymbolFile (mdbFilename, null);
+               public int CompileUnitCount {
+                       get { return ot.CompileUnitCount; }
                }
 
                public int SourceCount {
@@ -415,10 +420,17 @@ namespace Mono.CompilerServices.SymbolWriter
                        get { return guid; }
                }
 
+               public OffsetTable OffsetTable {
+                       get { return ot; }
+               }
+
                internal int LineNumberCount = 0;
                internal int LocalCount = 0;
                internal int StringSize = 0;
 
+               internal int LineNumberSize = 0;
+               internal int ExtendedLineNumberSize = 0;
+
                public SourceFileEntry GetSourceFile (int index)
                {
                        if ((index < 1) || (index > ot.SourceCount))
@@ -426,15 +438,21 @@ namespace Mono.CompilerServices.SymbolWriter
                        if (reader == null)
                                throw new InvalidOperationException ();
 
-                       SourceFileEntry source = (SourceFileEntry) source_file_hash [index];
-                       if (source != null)
-                               return source;
+                       lock (this) {
+                               SourceFileEntry source;
+                               if (source_file_hash.TryGetValue (index, out source))
+                                       return source;
+
+                               long old_pos = reader.BaseStream.Position;
 
-                       reader.BaseStream.Position = ot.SourceTableOffset +
-                               SourceFileEntry.Size * (index - 1);
-                       source = new SourceFileEntry (this, reader);
-                       source_file_hash.Add (index, source);
-                       return source;
+                               reader.BaseStream.Position = ot.SourceTableOffset +
+                                       SourceFileEntry.Size * (index - 1);
+                               source = new SourceFileEntry (this, reader);
+                               source_file_hash.Add (index, source);
+
+                               reader.BaseStream.Position = old_pos;
+                               return source;
+                       }
                }
 
                public SourceFileEntry[] Sources {
@@ -449,48 +467,77 @@ namespace Mono.CompilerServices.SymbolWriter
                        }
                }
 
-               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)
+               public CompileUnitEntry GetCompileUnit (int index)
                {
+                       if ((index < 1) || (index > ot.CompileUnitCount))
+                               throw new ArgumentException ();
                        if (reader == null)
                                throw new InvalidOperationException ();
 
-                       if (method_token_hash == null) {
-                               method_token_hash = new Hashtable ();
+                       lock (this) {
+                               CompileUnitEntry unit;
+                               if (compile_unit_hash.TryGetValue (index, out unit))
+                                       return unit;
 
-                               for (int i = 0; i < MethodCount; i++) {
-                                       MethodIndexEntry ie = GetMethodIndexEntry (i + 1);
+                               long old_pos = reader.BaseStream.Position;
 
-                                       method_token_hash.Add (ie.Token, i + 1);
-                               }
+                               reader.BaseStream.Position = ot.CompileUnitTableOffset +
+                                       CompileUnitEntry.Size * (index - 1);
+                               unit = new CompileUnitEntry (this, reader);
+                               compile_unit_hash.Add (index, unit);
+
+                               reader.BaseStream.Position = old_pos;
+                               return unit;
                        }
+               }
 
-                       object value = method_token_hash [token];
-                       if (value == null)
-                               return null;
+               public CompileUnitEntry[] CompileUnits {
+                       get {
+                               if (reader == null)
+                                       throw new InvalidOperationException ();
 
-                       return GetMethod ((int) value);
+                               CompileUnitEntry[] retval = new CompileUnitEntry [CompileUnitCount];
+                               for (int i = 0; i < CompileUnitCount; i++)
+                                       retval [i] = GetCompileUnit (i + 1);
+                               return retval;
+                       }
                }
 
-#if !CECIL
-               public MethodEntry GetMethod (MethodBase method)
+               void read_methods ()
+               {
+                       lock (this) {
+                               if (method_token_hash != null)
+                                       return;
+
+                               method_token_hash = new Dictionary<int, MethodEntry> ();
+                               method_list = new List<MethodEntry> ();
+
+                               long old_pos = reader.BaseStream.Position;
+                               reader.BaseStream.Position = ot.MethodTableOffset;
+
+                               for (int i = 0; i < MethodCount; i++) {
+                                       MethodEntry entry = new MethodEntry (this, reader, i + 1);
+                                       method_token_hash.Add (entry.Token, entry);
+                                       method_list.Add (entry);
+                               }
+
+                               reader.BaseStream.Position = old_pos;
+                       }
+               }
+
+               public MethodEntry GetMethodByToken (int token)
                {
                        if (reader == null)
                                throw new InvalidOperationException ();
-                       int token = MonoDebuggerSupport.GetMethodToken (method);
-                       return GetMethodByToken (token);
+
+                       lock (this) {
+                               read_methods ();
+                               MethodEntry me;
+                               method_token_hash.TryGetValue (token, out me);
+                               return me;
+                       }
                }
-#endif
-               
+
                public MethodEntry GetMethod (int index)
                {
                        if ((index < 1) || (index > ot.MethodCount))
@@ -498,16 +545,10 @@ namespace Mono.CompilerServices.SymbolWriter
                        if (reader == null)
                                throw new InvalidOperationException ();
 
-                       MethodEntry entry = (MethodEntry) method_hash [index];
-                       if (entry != null)
-                               return entry;
-
-                       MethodIndexEntry ie = GetMethodIndexEntry (index);
-                       reader.BaseStream.Position = ie.FileOffset;
-
-                       entry = new MethodEntry (this, reader, index);
-                       method_hash.Add (index, entry);
-                       return entry;
+                       lock (this) {
+                               read_methods ();
+                               return method_list [index - 1];
+                       }
                }
 
                public MethodEntry[] Methods {
@@ -515,33 +556,13 @@ namespace Mono.CompilerServices.SymbolWriter
                                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 ();
-
-                       object entry = method_source_hash [index];
-                       if (entry != null)
-                               return (MethodSourceEntry) entry;
-
-                       MethodEntry method = GetMethod (index);
-                       foreach (MethodSourceEntry source in method.SourceFile.Methods) {
-                               if (source.Index == index) {
-                                       method_source_hash.Add (index, source);
-                                       return source;
+                               lock (this) {
+                                       read_methods ();
+                                       MethodEntry[] retval = new MethodEntry [MethodCount];
+                                       method_list.CopyTo (retval, 0);
+                                       return retval;
                                }
                        }
-
-                       throw new MonoSymbolFileException ("Internal error.");
                }
 
                public int FindSource (string file_name)
@@ -549,37 +570,44 @@ namespace Mono.CompilerServices.SymbolWriter
                        if (reader == null)
                                throw new InvalidOperationException ();
 
-                       if (source_name_hash == null) {
-                               source_name_hash = new Hashtable ();
+                       lock (this) {
+                               if (source_name_hash == null) {
+                                       source_name_hash = new Dictionary<string, int> ();
 
-                               for (int i = 0; i < ot.SourceCount; i++) {
-                                       SourceFileEntry source = GetSourceFile (i + 1);
-
-                                       source_name_hash.Add (source.FileName, i);
+                                       for (int i = 0; i < ot.SourceCount; i++) {
+                                               SourceFileEntry source = GetSourceFile (i + 1);
+                                               source_name_hash.Add (source.FileName, i);
+                                       }
                                }
-                       }
 
-                       object value = source_name_hash [file_name];
-                       if (value == null)
-                               return -1;
-                       return (int) value;
+                               int value;
+                               if (!source_name_hash.TryGetValue (file_name, out value))
+                                       return -1;
+                               return value;
+                       }
                }
 
                public AnonymousScopeEntry GetAnonymousScope (int id)
                {
-                       if (anonymous_scopes != null)
-                               return (AnonymousScopeEntry) anonymous_scopes [id];
                        if (reader == null)
                                throw new InvalidOperationException ();
 
-                       anonymous_scopes = new Hashtable ();
-                       reader.BaseStream.Position = ot.AnonymousScopeTableOffset;
-                       for (int i = 0; i < ot.AnonymousScopeCount; i++) {
-                               AnonymousScopeEntry scope = new AnonymousScopeEntry (reader);
-                               anonymous_scopes.Add (scope.ID, scope);
-                       }
+                       AnonymousScopeEntry scope;
+                       lock (this) {
+                               if (anonymous_scopes != null) {
+                                       anonymous_scopes.TryGetValue (id, out scope);
+                                       return scope;
+                               }
+
+                               anonymous_scopes = new Dictionary<int, AnonymousScopeEntry> ();
+                               reader.BaseStream.Position = ot.AnonymousScopeTableOffset;
+                               for (int i = 0; i < ot.AnonymousScopeCount; i++) {
+                                       scope = new AnonymousScopeEntry (reader);
+                                       anonymous_scopes.Add (scope.ID, scope);
+                               }
 
-                       return (AnonymousScopeEntry) anonymous_scopes [id];
+                               return anonymous_scopes [id];
+                       }
                }
 
                internal MyBinaryReader BinaryReader {