Merge pull request #487 from mayerwin/patch-1
[mono.git] / mcs / tools / linker / Mono.Linker / LinkContext.cs
index 320885a6963167724a28ab14f384d045fbeb8944..8d97f8dc1504b62d710c91111c05e999ed479cab 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
+using System;
 using System.Collections;
 using System.IO;
+
 using Mono.Cecil;
+using Mono.Cecil.Cil;
 
 namespace Mono.Linker {
 
@@ -38,13 +41,25 @@ namespace Mono.Linker {
                AssemblyAction _coreAction;
                Hashtable _actions;
                string _outputDirectory;
+               Hashtable _parameters;
+               bool _linkSymbols;
 
                AssemblyResolver _resolver;
 
+               ReaderParameters _readerParameters;
+               ISymbolReaderProvider _symbolReaderProvider;
+               ISymbolWriterProvider _symbolWriterProvider;
+
+               AnnotationStore _annotations;
+
                public Pipeline Pipeline {
                        get { return _pipeline; }
                }
 
+               public AnnotationStore Annotations {
+                       get { return _annotations; }
+               }
+
                public string OutputDirectory {
                        get { return _outputDirectory; }
                        set { _outputDirectory = value; }
@@ -55,65 +70,119 @@ namespace Mono.Linker {
                        set { _coreAction = value; }
                }
 
+               public bool LinkSymbols {
+                       get { return _linkSymbols; }
+                       set { _linkSymbols = value; }
+               }
+
                public IDictionary Actions {
-                       get {
-                               if (_actions == null)
-                                       _actions = new Hashtable ();
-                               return _actions;
-                       }
+                       get { return _actions; }
                }
 
                public AssemblyResolver Resolver {
                        get { return _resolver; }
                }
 
+               public ISymbolReaderProvider SymbolReaderProvider {
+                       get { return _symbolReaderProvider; }
+                       set { _symbolReaderProvider = value; }
+               }
+
+               public ISymbolWriterProvider SymbolWriterProvider {
+                       get { return _symbolWriterProvider; }
+                       set { _symbolWriterProvider = value; }
+               }
+
                public LinkContext (Pipeline pipeline)
+                       : this (pipeline, new AssemblyResolver ())
+               {
+               }
+
+               public LinkContext (Pipeline pipeline, AssemblyResolver resolver)
                {
                        _pipeline = pipeline;
-                       _resolver = new AssemblyResolver ();
+                       _resolver = resolver;
+                       _actions = new Hashtable ();
+                       _parameters = new Hashtable ();
+                       _annotations = new AnnotationStore ();
+                       _readerParameters = new ReaderParameters {
+                               AssemblyResolver = _resolver,
+                       };
                }
 
-               public TypeDefinition GetType (string type)
+               public TypeDefinition GetType (string fullName)
                {
-                       int pos = type.IndexOf (",");
-                       type = type.Replace ("+", "/");
+                       int pos = fullName.IndexOf (",");
+                       fullName = fullName.Replace ("+", "/");
                        if (pos == -1) {
-                               foreach (AssemblyDefinition asm in GetAssemblies ())
-                                       if (asm.MainModule.Types.Contains (type))
-                                               return asm.MainModule.Types [type];
+                               foreach (AssemblyDefinition asm in GetAssemblies ()) {
+                                       var type = asm.MainModule.GetType (fullName);
+                                       if (type != null)
+                                               return type;
+                               }
 
                                return null;
                        }
 
-                       string asmname = type.Substring (pos + 1);
-                       type = type.Substring (0, pos);
+                       string asmname = fullName.Substring (pos + 1);
+                       fullName = fullName.Substring (0, pos);
                        AssemblyDefinition assembly = Resolve (AssemblyNameReference.Parse (asmname));
-                       return assembly.MainModule.Types [type];
+                       return assembly.MainModule.GetType (fullName);
                }
 
                public AssemblyDefinition Resolve (string name)
                {
                        if (File.Exists (name)) {
-                               AssemblyDefinition assembly = AssemblyFactory.GetAssembly (name);
+                               AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly (name, _readerParameters);
                                _resolver.CacheAssembly (assembly);
                                return assembly;
-                       } else {
-                               AssemblyNameReference reference = new AssemblyNameReference ();
-                               reference.Name = name;
-                               return Resolve (reference);
                        }
+
+                       return Resolve (new AssemblyNameReference (name, new Version ()));
                }
 
                public AssemblyDefinition Resolve (IMetadataScope scope)
                {
                        AssemblyNameReference reference = GetReference (scope);
+                       try {
+                               AssemblyDefinition assembly = _resolver.Resolve (reference, _readerParameters);
+
+                               if (SeenFirstTime (assembly)) {
+                                       SafeReadSymbols (assembly);
+                                       SetAction (assembly);
+                               }
 
-                       AssemblyDefinition assembly = _resolver.Resolve (reference);
+                               return assembly;
+                       }
+                       catch {
+                               throw new AssemblyResolutionException (reference);
+                       }
+               }
 
-                       if (!Annotations.HasAction (assembly))
-                               SetAction (assembly);
+               bool SeenFirstTime (AssemblyDefinition assembly)
+               {
+                       return !_annotations.HasAction (assembly);
+               }
 
-                       return assembly;
+               public void SafeReadSymbols (AssemblyDefinition assembly)
+               {
+                       if (!_linkSymbols)
+                               return;
+
+                       if (assembly.MainModule.HasSymbols)
+                               return;
+
+                       try {
+                               if (_symbolReaderProvider != null) {
+                                       var symbolReader = _symbolReaderProvider.GetSymbolReader (
+                                               assembly.MainModule,
+                                               assembly.MainModule.FullyQualifiedName);
+
+                                       _annotations.AddSymbolReader (assembly, symbolReader);
+                                       assembly.MainModule.ReadSymbols (symbolReader);
+                               } else
+                                       assembly.MainModule.ReadSymbols ();
+                       } catch {}
                }
 
                static AssemblyNameReference GetReference (IMetadataScope scope)
@@ -139,15 +208,20 @@ namespace Mono.Linker {
                        else if (IsCore (name))
                                action = _coreAction;
 
-                       Annotations.SetAction (assembly, action);
+                       _annotations.SetAction (assembly, action);
                }
 
                static bool IsCore (AssemblyNameReference name)
                {
-                       return name.Name == "mscorlib"
-                               || name.Name == "Accessibility"
-                               || name.Name.StartsWith ("System")
-                               || name.Name.StartsWith ("Microsoft");
+                       switch (name.Name) {
+                       case "mscorlib":
+                       case "Accessibility":
+                       case "Mono.Security":
+                               return true;
+                       default:
+                               return name.Name.StartsWith ("System")
+                                       || name.Name.StartsWith ("Microsoft");
+                       }
                }
 
                public AssemblyDefinition [] GetAssemblies ()
@@ -157,5 +231,20 @@ namespace Mono.Linker {
                        cache.Values.CopyTo (asms, 0);
                        return asms;
                }
+
+               public void SetParameter (string key, string value)
+               {
+                       _parameters [key] = value;
+               }
+
+               public bool HasParameter (string key)
+               {
+                       return _parameters.Contains (key);
+               }
+
+               public string GetParameter (string key)
+               {
+                       return (string) _parameters [key];
+               }
        }
 }