/// <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); }
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); }
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); } }
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); }