Exemplo n.º 1
0
        /// <summary>
        /// Traverse the given assembly (located in options.Assembly) for contracts and return the contracts.
        /// </summary>
        /// <remarks>
        /// We use dictionary mapping special string ids that are unique to each member in an XML file to
        /// the contracts that that member has.
        /// </remarks>
        static IDictionary <string, XContract[]> GetContracts(Options options, DocTracker docTracker)
        {
            Contract.Requires(options != null);
            Contract.Requires(docTracker != null);
            Contract.Ensures(Contract.Result <IDictionary <string, XContract[]> >() != null);

            #region Establish host and load assembly

            Contract.Assume(options.resolvedPaths != null);

            var host = new CodeContractAwareHostEnvironment(options.libpaths);
            foreach (var p in options.resolvedPaths)
            {
                host.AddResolvedPath(p);
            }
            IModule module = host.LoadUnitFrom(options.assembly) as IModule;
            if (module == null || module == Dummy.Module || module == Dummy.Assembly)
            {
                Console.WriteLine("'{0}' is not a PE file containing a CLR module or assembly.", options.assembly);
                Environment.Exit(1);
            }
            #endregion
            #region Create the contracts dictionary
            Dictionary <string, XContract[]> contracts = new Dictionary <string, XContract[]>(StringComparer.Ordinal); //Use Ordinal compare for faster string comparison.
            #endregion
            #region Traverse module and extract contracts
            var contractsVisitor = new ContractVisitor(host, contracts, options, docTracker);
            var traverser        = new ContractTraverser(host);
            traverser.PreorderVisitor = contractsVisitor;
            traverser.Traverse(module);
            #endregion
            return(contracts);
        }
Exemplo n.º 2
0
        protected IModule LoadModuleInHost(FileInfo inputFile)
        {
            Contract.Requires(inputFile.Exists);

            var module = host.LoadUnitFrom(inputFile.FullName) as IModule;

            if (module == null || module is Dummy || module == Dummy.Assembly)
            {
                throw new Exception(string.Format("{0} is not a PE file containing a CLR module or assembly.", inputFile.FullName));
            }
            return(module);
        }
Exemplo n.º 3
0
        static int Main(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                Console.WriteLine("usage: HelloContracts [path]fileName.Contracts.dll [-libpaths ...]* [-p [-i] | -inject]");
                return(1);
            }
            #region Parse options
            var options = new Options();
            options.Parse(args);
            if (options.HelpRequested)
            {
                options.PrintOptions("");
                return(1);
            }
            if (options.HasErrors)
            {
                options.PrintErrorsAndExit(Console.Out);
            }
            #endregion

            var fileName = String.IsNullOrEmpty(options.assembly) ? options.GeneralArguments[0] : options.assembly;

            if (options.printContracts)
            {
                #region Collect and write contracts
                using (var host = new CodeContractAwareHostEnvironment(options.libpaths)) {
                    IModule module = host.LoadUnitFrom(fileName) as IModule;
                    if (module == null || module is Dummy)
                    {
                        Console.WriteLine("'{0}' is not a PE file containing a CLR module or assembly.", fileName);
                        Environment.Exit(1);
                    }
                    var t = new Traverser(host, options.inherited);
                    t.Traverse(module);
                }
                #endregion
                return(0);
            }
            else
            {
                using (var host = new CodeContractAwareHostEnvironment(options.libpaths, true, true)) {
                    // Read the Metadata Model from the PE file
                    var module = host.LoadUnitFrom(fileName) as IModule;
                    if (module == null || module is Dummy)
                    {
                        Console.WriteLine(fileName + " is not a PE file containing a CLR module or assembly.");
                        return(1);
                    }

                    // Get a PDB reader if there is a PDB file.
                    PdbReader /*?*/ pdbReader = null;
                    string          pdbFile   = Path.ChangeExtension(module.Location, "pdb");
                    if (File.Exists(pdbFile))
                    {
                        using (var pdbStream = File.OpenRead(pdbFile)) {
                            pdbReader = new PdbReader(pdbStream, host);
                        }
                    }

                    using (pdbReader) {
                        ISourceLocationProvider sourceLocationProvider = pdbReader;

                        // Construct a Code Model from the Metadata model via decompilation
                        var mutableModule = Decompiler.GetCodeModelFromMetadataModel(host, module, pdbReader, DecompilerOptions.AnonymousDelegates | DecompilerOptions.Loops);
                        ILocalScopeProvider localScopeProvider = new Decompiler.LocalScopeProvider(pdbReader);

                        // Extract contracts (side effect: removes them from the method bodies)
                        var contractProvider = Microsoft.Cci.MutableContracts.ContractHelper.ExtractContracts(host, mutableModule, pdbReader, localScopeProvider);

                        // Inject non-null postconditions
                        if (options.inject)
                        {
                            new NonNullInjector(host, contractProvider).Traverse(mutableModule);
                        }

                        // Put the contracts back in as method calls at the beginning of each method
                        Microsoft.Cci.MutableContracts.ContractHelper.InjectContractCalls(host, mutableModule, contractProvider, sourceLocationProvider);

                        // Write out the resulting module. Each method's corresponding IL is produced
                        // lazily using CodeModelToILConverter via the delegate that the mutator stored in the method bodies.
                        using (var peStream = File.Create(mutableModule.Location + ".pe")) {
                            if (pdbReader == null)
                            {
                                PeWriter.WritePeToStream(mutableModule, host, peStream);
                            }
                            else
                            {
                                using (var pdbWriter = new PdbWriter(mutableModule.Location + ".pdb", sourceLocationProvider)) {
                                    PeWriter.WritePeToStream(mutableModule, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter);
                                }
                            }
                        }
                    }
                }
                return(0);
            }
        }
Exemplo n.º 4
0
        public static Bpl.Program /*?*/ TranslateAssembly(List <string> assemblyNames, HeapFactory heapFactory, Options options, List <Regex> exemptionList, bool whiteList)
        {
            Contract.Requires(assemblyNames != null);
            Contract.Requires(heapFactory != null);

            var       libPaths       = options.libpaths;
            var       wholeProgram   = options.wholeProgram;
            var /*?*/ stubAssemblies = options.stub;

            var host = new CodeContractAwareHostEnvironment(libPaths != null ? libPaths : Enumerable <string> .Empty, true, true);

            Host = host;

            Bpl.CommandLineOptions.Install(new Bpl.CommandLineOptions());

            #region Assemlies to translate (via cmd line)
            modules = new List <IModule>();
            var contractExtractors = new Dictionary <IUnit, IContractProvider>();
            var pdbReaders         = new Dictionary <IUnit, PdbReader>();
            #region Load *all* of the assemblies before doing anything else so that they can all vote on unification matters
            foreach (var a in assemblyNames)
            {
                var module = host.LoadUnitFrom(a) as IModule;
                if (module == null || module == Dummy.Module || module == Dummy.Assembly)
                {
                    Console.WriteLine(a + " is not a PE file containing a CLR module or assembly, or an error occurred when loading it.");
                    Console.WriteLine("Skipping it, continuing with other input assemblies");
                    continue;
                }
                modules.Add(module);
            }
            #endregion
            #region Decompile all of the assemblies
            var decompiledModules = new List <IModule>();
            foreach (var m in modules)
            {
                PdbReader /*?*/ pdbReader = null;
                string          pdbFile   = Path.ChangeExtension(m.Location, "pdb");
                if (File.Exists(pdbFile))
                {
                    Stream pdbStream = File.OpenRead(pdbFile);
                    pdbReader = new PdbReader(pdbStream, host);
                }
                var m2 = Decompiler.GetCodeModelFromMetadataModel(host, m, pdbReader, DecompilerOptions.Unstack) as IModule;
                // The decompiler does not turn calls to Assert/Assume into Code Model nodes
                m2 = new Microsoft.Cci.MutableContracts.ContractExtractor.AssertAssumeExtractor(host, pdbReader).Rewrite(m2);
                decompiledModules.Add(m2);
                host.RegisterAsLatest(m2);
                contractExtractors.Add(m2, host.GetContractExtractor(m2.UnitIdentity));
                pdbReaders.Add(m2, pdbReader);
            }
            modules = decompiledModules;
            #endregion
            #endregion

            #region Assemblies to translate (stubs)
            if (stubAssemblies != null)
            {
                foreach (var s in stubAssemblies)
                {
                    var module = host.LoadUnitFrom(s) as IModule;
                    if (module == null || module == Dummy.Module || module == Dummy.Assembly)
                    {
                        Console.WriteLine(s + " is not a PE file containing a CLR module or assembly, or an error occurred when loading it.");
                        Console.WriteLine("Skipping it, continuing with other input assemblies");
                    }
                    PdbReader /*?*/ pdbReader = null;
                    string          pdbFile   = Path.ChangeExtension(module.Location, "pdb");
                    if (File.Exists(pdbFile))
                    {
                        Stream pdbStream = File.OpenRead(pdbFile);
                        pdbReader = new PdbReader(pdbStream, host);
                    }
                    module = Decompiler.GetCodeModelFromMetadataModel(host, module, pdbReader, DecompilerOptions.Unstack) as IModule;

                    var copier        = new CodeDeepCopier(host);
                    var mutableModule = copier.Copy(module);

                    var mscorlib = TypeHelper.GetDefiningUnit(host.PlatformType.SystemObject.ResolvedType);

                    //var mutator = new ReparentModule(host, mscorlib, mutableModule);
                    //module = mutator.Rewrite(mutableModule);
                    //modules.Add(Tuple.Create(module, pdbReader));

                    RewriteUnitReferences renamer = new RewriteUnitReferences(host, mutableModule);
                    var mscorlibAssembly          = (IAssembly)mscorlib;
                    renamer.targetAssembly           = mscorlibAssembly;
                    renamer.originalAssemblyIdentity = mscorlibAssembly.AssemblyIdentity;
                    renamer.RewriteChildren(mutableModule);
                    modules.Add((IModule)mutableModule);
                    contractExtractors.Add(module, host.GetContractExtractor(module.UnitIdentity));
                    pdbReaders.Add(module, pdbReader);
                }
            }
            #endregion

            if (modules.Count == 0)
            {
                throw new TranslationException("No input assemblies to translate.");
            }

            //var primaryModule = modules[0];
            Sink sink = new Sink(host, heapFactory, options, exemptionList, whiteList);
            TranslationHelper.tmpVarCounter = 0;

            // TODO move away, get all plugin and translators from a config file or alike
            #region Plugged translators
            List <Translator>  translatorsPlugged = new List <Translator>();
            ITranslationPlugin bctPlugin          = new BytecodeTranslatorPlugin(wholeProgram);
            Translator         bcTranslator       = bctPlugin.getTranslator(sink, contractExtractors, pdbReaders);
            translatorsPlugged.Add(bcTranslator);

            #endregion
            sink.TranslationPlugins = translatorsPlugged;

            // TODO replace the whole translation by a translator initialization and an orchestrator calling back for each element
            // TODO for the current BC translator it will possibly just implement onMetadataElement(IModule)
            // TODO refactor this away, handle priorities between plugged translators
            IOrderedEnumerable <Translator> prioritizedTranslators = translatorsPlugged.OrderBy(t => t.getPriority());
            foreach (Translator t in prioritizedTranslators)
            {
                t.initialize();
                if (t.isOneShot())
                {
                    t.TranslateAssemblies(modules);
                }
            }

            foreach (var pair in sink.delegateTypeToDelegates.Values)
            {
                CreateDispatchMethod(sink, pair.Item1, pair.Item2);
                CreateDelegateCreateMethod(sink, pair.Item1, pair.Item2);
                CreateDelegateAddMethod(sink, pair.Item1, pair.Item2);
                CreateDelegateRemoveMethod(sink, pair.Item1, pair.Item2);
            }

            // Subtyping for extern types
            if (sink.Options.typeInfo > 0)
            {
                sink.DeclareExternTypeSubtyping();
            }

            //sink.CreateIdentifierCorrespondenceTable(primaryModule.Name.Value);

            //var rc = new Bpl.ResolutionContext((Bpl.IErrorSink)null);
            //foreach (var decl in sink.TranslatedProgram.TopLevelDeclarations) {
            //  decl.Register(rc);
            //}
            //sink.TranslatedProgram.Resolve(rc);
            //var goodDecls = new List<Bpl.Declaration>();
            //var tc = new Bpl.TypecheckingContext(null);
            //foreach (var decl in sink.TranslatedProgram.TopLevelDeclarations) {
            //  var impl = decl as Bpl.Implementation;
            //  if (impl == null) {
            //    goodDecls.Add(decl);
            //    continue;
            //  }
            //  try {
            //    //var tc = new Bpl.TypecheckingContext(null);
            //    impl.Typecheck(tc);
            //    goodDecls.Add(impl);
            //  } catch {
            //    Console.WriteLine("Deleting implementation for: " + impl.Name);
            //    // nothing to do, just continue
            //  }
            //}
            //sink.TranslatedProgram.TopLevelDeclarations = goodDecls;
            return(sink.TranslatedProgram);
        }