// // LinkContext.cs // // Author: // Jb Evain (jbevain@gmail.com) // // (C) 2006 Jb Evain // // 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.Collections; using System.IO; using Mono.Cecil; using Mono.Cecil.Cil; namespace Mono.Linker { public class LinkContext { Pipeline _pipeline; 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; } } public AssemblyAction CoreAction { get { return _coreAction; } set { _coreAction = value; } } public bool LinkSymbols { get { return _linkSymbols; } set { _linkSymbols = value; } } public IDictionary Actions { get { return _actions; } } public AssemblyResolver Resolver { get { return _resolver; } } public ISymbolReaderProvider SymbolReaderProvider { get { return _symbolReaderProvider; } set { _symbolReaderProvider = value; _readerParameters.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 = resolver; _actions = new Hashtable (); _parameters = new Hashtable (); _annotations = new AnnotationStore (); _readerParameters = new ReaderParameters { AssemblyResolver = _resolver, }; } public TypeDefinition GetType (string fullName) { int pos = fullName.IndexOf (","); fullName = fullName.Replace ("+", "/"); if (pos == -1) { foreach (AssemblyDefinition asm in GetAssemblies ()) { var type = asm.MainModule.GetType (fullName); if (type != null) return type; } return null; } string asmname = fullName.Substring (pos + 1); fullName = fullName.Substring (0, pos); AssemblyDefinition assembly = Resolve (AssemblyNameReference.Parse (asmname)); return assembly.MainModule.GetType (fullName); } public AssemblyDefinition Resolve (string name) { if (File.Exists (name)) { AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly (name, _readerParameters); _resolver.CacheAssembly (assembly); return assembly; } return Resolve (new AssemblyNameReference (name, new Version ())); } public AssemblyDefinition Resolve (IMetadataScope scope) { AssemblyNameReference reference = GetReference (scope); AssemblyDefinition assembly = _resolver.Resolve (reference, _readerParameters); if (SeenFirstTime (assembly)) { SafeReadSymbols (assembly); SetAction (assembly); } return assembly; } bool SeenFirstTime (AssemblyDefinition assembly) { return !_annotations.HasAction (assembly); } public void SafeReadSymbols (AssemblyDefinition assembly) { try { if (_symbolReaderProvider != null) { var symbolReader = _symbolReaderProvider.GetSymbolReader ( assembly.MainModule, assembly.MainModule.FullyQualifiedName); assembly.MainModule.ReadSymbols (symbolReader); } else assembly.MainModule.ReadSymbols (); } catch {} } static AssemblyNameReference GetReference (IMetadataScope scope) { AssemblyNameReference reference; if (scope is ModuleDefinition) { AssemblyDefinition asm = ((ModuleDefinition) scope).Assembly; reference = asm.Name; } else reference = (AssemblyNameReference) scope; return reference; } void SetAction (AssemblyDefinition assembly) { AssemblyAction action = AssemblyAction.Link; AssemblyNameDefinition name = assembly.Name; if (_actions.Contains (name.Name)) action = (AssemblyAction) _actions [name.Name]; else if (IsCore (name)) action = _coreAction; _annotations.SetAction (assembly, action); } static bool IsCore (AssemblyNameReference name) { 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 () { IDictionary cache = _resolver.AssemblyCache; AssemblyDefinition [] asms = new AssemblyDefinition [cache.Count]; 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]; } } }