Ejemplo n.º 1
0
 private INamespaceTypeDefinition /*?*/ GetFirstMatchingTypeDefinition(AsmMetaHostEnvironment host, INamespaceDefinition nameSpace, string name)
 {
     foreach (var mem in nameSpace.GetMembersNamed(host.NameTable.GetNameFor(name), false))
     {
         var ntd = mem as INamespaceTypeDefinition;
         if (ntd != null)
         {
             return(ntd);
         }
     }
     return(null);
 }
Ejemplo n.º 2
0
 /// <summary>
 /// Use this constructor when you don't want some things emitted into the output.
 /// For instance, if <paramref name="e"/> is <code>EmitOptions.ExtVis</code>
 /// then all methods, types, etc., that are not visible outside of the assembly are not emitted into the output.
 /// </summary>
 /// <param name="e">
 /// Indicates what to emit and what to leave out.
 /// For instance, if it is <code>EmitOptions.ExtVis</code>
 /// then all methods, types, etc., that are not visible outside of the assembly
 /// are not emitted into the output.
 /// </param>
 /// <param name="keepAttributes">
 /// Specify whether to keep custom attributes on types, methods, assembly, etc.
 /// </param>
 /// <param name="exemptAttributes">
 /// A list of attribute names that are exempt from the polarity of <paramref name="keepAttributes"/>.
 /// For instance, if <paramref name="keepAttributes"/> is true, then if an attribute is in the list, that
 /// means to not emit it. Conversely, if <paramref name="keepAttributes"/> is false, then if it is in the
 /// list, it means to emit it.
 /// </param>
 /// <param name="backwardCompatibility">
 /// When true, then this behaves just like the original AsmMeta. That means, among other things, that the argument values
 /// of <paramref name="e"/> and <paramref name="keepAttributes"/> are ignored and the values KeepOptions.ExtVis and
 /// false, respectively, are used instead.
 /// </param>
 public DeleteThings(AsmMetaHostEnvironment host, KeepOptions e, SecurityKeepOptions transparency, bool keepAttributes, string[] exemptAttributes, bool backwardCompatibility)
     : base(host)
 {
     this.asmMetaHostEnvironment = host;
     if (backwardCompatibility)
     {
         this.WhatToKeep         = KeepOptions.ExtVis;
         this.KeepAttributes     = false;
         this.backwardCompat     = true;
         this.SecurityWhatToKeep = SecurityKeepOptions.All;
     }
     else
     {
         this.WhatToKeep         = e;
         this.KeepAttributes     = keepAttributes;
         this.SecurityWhatToKeep = transparency;
     }
     for (int i = 0, n = exemptAttributes == null ? 0 : exemptAttributes.Length; i < n; i++)
     {
         this.ExemptAttributes[exemptAttributes[i]] = true;
     }
 }
Ejemplo n.º 3
0
        internal int Run()
        {
            SecurityKeepOptions securityKeepOptions = options.onlySecurityTransparent ? SecurityKeepOptions.OnlyNonCritical : SecurityKeepOptions.All;

            if (options.doBreak)
            {
                System.Diagnostics.Debugger.Launch();
            }

            string assemblyName = null;

            if (options.GeneralArguments.Count == 1)
            {
                assemblyName = options.GeneralArguments[0];
            }
            if (assemblyName == null)
            {
                errorLogger("Must specify an input file.");
                return(1);
            }

            using (var host = new AsmMetaHostEnvironment(options.libPaths.ToArray(), options.searchGAC))
            {
                foreach (var p in options.resolvedPaths)
                {
                    host.AddResolvedPath(p);
                }

                IAssembly /*?*/ assembly = host.LoadUnitFrom(assemblyName) as IAssembly;
                if (assembly == null || assembly is Dummy)
                {
                    errorLogger(assemblyName + " is not a PE file containing a CLR assembly, or an error occurred when loading it.");
                    return(1);
                }

                var rewrittenAttribute = CreateTypeReference(host, assembly, "System.Diagnostics.Contracts.RuntimeContractsAttribute");
                if (AttributeHelper.Contains(assembly.Attributes, rewrittenAttribute))
                {
                    errorLogger(assemblyName + " is already rewritten, cannot generate a reference assembly from it.");
                    return(1);
                }

                if (options.backwardCompatibility)
                { // redundant because RemoveMethodBodies.ctor also does this when the flag is set
                    options.whatToEmit     = KeepOptions.ExtVis;
                    options.emitAttributes = false;
                }

                PdbReader /*?*/ pdbReader = null;
                if (options.includeSourceTextInContract)
                { // No point getting the PDB file unless we want to use it for source text
                    string pdbFile = Path.ChangeExtension(assembly.Location, "pdb");
                    if (File.Exists(pdbFile))
                    {
                        using (var pdbStream = File.OpenRead(pdbFile))
                        {
                            pdbReader = new PdbReader(pdbStream, host);
                        }
                    }
                    else
                    {
                        errorLogger("Could not load the PDB file for the assembly '" + assembly.Name.Value + "' . Source text will not be preserved in the reference assembly. Proceeding anyway.");
                    }
                }
                using (pdbReader)
                {
                    // We might be working on the assembly that defines the contract class and/or the type System.Void.
                    // (Or any other platform type!)
                    // But the host.PlatformType object has not been duplicated, so its properties will continue to be references to the immutable ones.
                    // This is OK, except if the assembly is being renamed.
                    this.compilerGeneratedAttributeType = host.PlatformType.SystemRuntimeCompilerServicesCompilerGeneratedAttribute;
                    this.contractClassType   = host.PlatformType.SystemDiagnosticsContractsContract;
                    this.systemAttributeType = host.PlatformType.SystemAttribute;
                    this.systemBooleanType   = host.PlatformType.SystemBoolean;
                    this.systemStringType    = host.PlatformType.SystemString;
                    this.systemObjectType    = host.PlatformType.SystemObject;
                    this.systemVoidType      = host.PlatformType.SystemVoid;
                    //new FindPlatformTypes(this).Traverse(assembly); //update the above fields if any of those types are defined in mutable

                    Assembly mutable = new MetadataDeepCopier(host).Copy(assembly);

                    #region Rename the assembly in a separate pass because things done in later passes depend on interned keys that are computed based (in part) on the assembly identity

                    if (options.rename)
                    {
                        if (options.output != null)
                        {
                            mutable.Name = host.NameTable.GetNameFor(Path.GetFileNameWithoutExtension(options.output));
                        }
                        else
                        {
                            mutable.Name = host.NameTable.GetNameFor(assembly.Name.Value + ".Contracts");
                        }
                        mutable.ModuleName = mutable.Name;
                        mutable.Kind       = ModuleKind.DynamicallyLinkedLibrary;
                        mutable            = (Assembly)RenameAssembly.ReparentAssemblyIdentity(host, assembly.AssemblyIdentity, mutable.AssemblyIdentity, mutable);
                    }

                    #endregion Rename the assembly in a separate pass because things done in later passes depend on interned keys that are computed based (in part) on the assembly identity
                    if (!options.renameOnly)
                    {
                        if (options.contracts)
                        {
                            if (options.rename)
                            {
                                // We might be working on the assembly that defines the contract class and/or the type System.Void.
                                // (Or any other platform type!)
                                // But the host.PlatformType object has not been duplicated, so its properties will continue to be references to the immutable ones.
                                // This is OK, except if the assembly is being renamed.

                                var systemNamespace = GetFirstMatchingNamespace(host, mutable.UnitNamespaceRoot, "System");
                                if (systemNamespace != null)
                                {
                                    var typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Attribute");
                                    if (typeDefinition != null)
                                    {
                                        this.systemAttributeType = typeDefinition;
                                    }
                                    typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Boolean");
                                    if (typeDefinition != null)
                                    {
                                        this.systemBooleanType = typeDefinition;
                                    }
                                    typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Object");
                                    if (typeDefinition != null)
                                    {
                                        this.systemObjectType = typeDefinition;
                                    }
                                    typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "String");
                                    if (typeDefinition != null)
                                    {
                                        this.systemStringType = typeDefinition;
                                    }
                                    typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Void");
                                    if (typeDefinition != null)
                                    {
                                        this.systemVoidType = typeDefinition;
                                    }

                                    var systemRuntimeNamespace = GetFirstMatchingNamespace(host, systemNamespace, "Runtime");
                                    if (systemRuntimeNamespace != null)
                                    {
                                        var systemRuntimeCompilerServicesNamespace = GetFirstMatchingNamespace(host, systemRuntimeNamespace, "CompilerServices");
                                        if (systemRuntimeCompilerServicesNamespace != null)
                                        {
                                            typeDefinition = GetFirstMatchingTypeDefinition(host, systemRuntimeCompilerServicesNamespace, "CompilerGeneratedAttribute");
                                            if (typeDefinition != null)
                                            {
                                                this.compilerGeneratedAttributeType = typeDefinition;
                                            }
                                        }
                                    }

                                    var systemDiagnosticsNamespace = GetFirstMatchingNamespace(host, systemNamespace, "Diagnostics");
                                    if (systemDiagnosticsNamespace != null)
                                    {
                                        var systemDiagnosticsContractsNamespace = GetFirstMatchingNamespace(host, systemDiagnosticsNamespace, "Contracts");
                                        if (systemDiagnosticsContractsNamespace != null)
                                        {
                                            typeDefinition = GetFirstMatchingTypeDefinition(host, systemDiagnosticsContractsNamespace, "Contract");
                                            if (typeDefinition != null)
                                            {
                                                this.contractClassType = typeDefinition;
                                            }
                                        }
                                    }
                                }
                            }

                            mutable = AsmMetaRewriter.RewriteModule(host,
                                                                    pdbReader,
                                                                    mutable,
                                                                    contractClassType,
                                                                    compilerGeneratedAttributeType,
                                                                    systemAttributeType,
                                                                    systemBooleanType,
                                                                    systemObjectType,
                                                                    systemStringType,
                                                                    systemVoidType
                                                                    ) as Assembly;
                        }
                        #region Delete things that are not to be kept
                        if (options.backwardCompatibility || options.whatToEmit != KeepOptions.All || !options.emitAttributes || (options.attrs != null && 0 < options.attrs.Count))
                        {
                            DeleteThings thinner = new DeleteThings(host, options.whatToEmit, securityKeepOptions, options.emitAttributes, options.attrs.ToArray(), options.backwardCompatibility);
                            if (securityKeepOptions == SecurityKeepOptions.OnlyNonCritical && host.platformType.SystemSecuritySecurityCriticalAttribute.ResolvedType is Dummy)
                            {
                                errorLogger("You asked to remove security critical methods, but the version of mscorlib doesn't support the SecurityCriticalAttribute.");
                                return(1);
                            }
                            thinner.RewriteChildren(mutable);
                            #region Fix up dangling references to things that were deleted
                            FixUpReferences patcher = new FixUpReferences(host, thinner.WhackedMethods, thinner.WhackedTypes);
                            patcher.RewriteChildren(mutable);
                            #endregion Fix up dangling references to things that were deleted
                        }
                        #endregion Delete things that are not to be kept
                        #region Output is always a dll, so mark the assembly as that
                        mutable.EntryPoint = Dummy.MethodReference;
                        mutable.Kind       = ModuleKind.DynamicallyLinkedLibrary;
                        #endregion Output is always a dll, so mark the assembly as that
                    }

                    assembly = mutable;

                    string outputPath;
                    if (options.output != null) // user specified, they'd better make sure it doesn't conflict with anything
                    {
                        outputPath = options.output;
                    }
                    else if (options.rename) // A.dll ==> A.Contracts.dll (Always! Even if the input is an exe!)
                    {
                        outputPath = assembly.Name.Value + ".dll";
                    }
                    else // A.dll ==> A.dll.meta
                    {
                        outputPath = assembly.Name.Value + Path.GetExtension(assemblyName) + ".meta";
                    }
                    // NB: Do *not* pass a pdbWriter to WritePeToStream. No need to create a PDB file and if
                    // it is provided, then it might find things (like constants in a scope) that don't get
                    // visited and so don't have any type references modified as they should be.
                    using (var outputFile = File.Create(outputPath))
                    {
                        if (pdbReader != null && options.writePDB)
                        {
                            using (var pdbWriter = new PdbWriter(Path.ChangeExtension(outputPath, "pdb"), pdbReader))
                            {
                                // Need to not pass in a local scope provider until such time as we have one that will use the mutator
                                // to remap things (like the type of a scope constant) from the original assembly to the mutated one.
                                PeWriter.WritePeToStream(assembly, host, outputFile, pdbReader, null /*pdbReader*/, pdbWriter);
                            }
                        }
                        else
                        {
                            PeWriter.WritePeToStream(assembly, host, outputFile);
                        }
                    }
                }
            }
            return(0); // success
        }