public static IUnit ReparentAssemblyIdentity(IMetadataHost host, AssemblyIdentity targetAssemblyIdentity, AssemblyIdentity sourceAssemblyIdentity, IUnit unit) { Contract.Requires(targetAssemblyIdentity != null); Contract.Requires(sourceAssemblyIdentity != null); var rar = new RenameAssembly(host); rar.originalAssemblyIdentity = targetAssemblyIdentity; rar.replacementAssemblyReference = new Microsoft.Cci.Immutable.AssemblyReference(host, sourceAssemblyIdentity); return(rar.Rewrite(unit)); }
public static IUnit ReparentAssemblyIdentity(IMetadataHost host, AssemblyIdentity targetAssemblyIdentity, AssemblyIdentity sourceAssemblyIdentity, IUnit unit) { Contract.Requires(targetAssemblyIdentity != null); Contract.Requires(sourceAssemblyIdentity != null); var rar = new RenameAssembly(host); rar.originalAssemblyIdentity = targetAssemblyIdentity; rar.replacementAssemblyReference = new Microsoft.Cci.Immutable.AssemblyReference(host, sourceAssemblyIdentity); return rar.Rewrite(unit); }
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 }