Example #1
0
        public override void Visit(ITypeExport aliasForType)
        {
            this.Visit(aliasForType.GetAttributes(Context));

            // do not visit the reference to aliased type, it does not get into the type ref table based only on its membership of the exported types collection.
            // but DO visit the reference to assembly (if any) that defines the aliased type. That assembly might not already be in the assembly reference list.
            var definingUnit     = PeWriter.GetDefiningUnitReference(aliasForType.ExportedType, Context);
            var definingAssembly = definingUnit as IAssemblyReference;

            if (definingAssembly != null)
            {
                this.Visit(definingAssembly);
            }

            var definingModule = definingUnit as IModuleReference;

            if (definingModule != null)
            {
                definingAssembly = definingModule.GetContainingAssembly(Context);
                if (definingAssembly != null && !ReferenceEquals(definingAssembly, this.module.GetContainingAssembly(Context)))
                {
                    this.Visit(definingAssembly);
                }
            }
        }
Example #2
0
        public void WriteDefinitionLocations(PeWriter peWriter, MultiDictionary <Cci.DebugSourceDocument, Cci.DefinitionWithLocation> file2definitions)
        {
            ISymUnmanagedWriter5 writer5 = this.symWriter as ISymUnmanagedWriter5;

            if ((object)writer5 != null)
            {
                // NOTE: ISymUnmanagedWriter5 reports HRESULT = 0x806D000E in case we open and close
                //       the map without writing any resords with MapTokenToSourceSpan(...)
                bool open = false;

                foreach (var doc in file2definitions.Keys)
                {
                    ISymUnmanagedDocumentWriter docWriter = GetDocumentWriter(doc);
                    foreach (var definition in file2definitions[doc])
                    {
                        if (!open)
                        {
                            try
                            {
                                writer5.OpenMapTokensToSourceSpans();
                            }
                            catch (Exception ex)
                            {
                                throw new PdbWritingException(ex);
                            }

                            open = true;
                        }

                        uint token = peWriter.GetTokenForDefinition(definition.Definition);
                        Debug.Assert(token != 0);

                        try
                        {
                            writer5.MapTokenToSourceSpan(token, docWriter,
                                                         definition.StartLine + 1, definition.StartColumn + 1, definition.EndLine + 1, definition.EndColumn + 1);
                        }
                        catch (Exception ex)
                        {
                            throw new PdbWritingException(ex);
                        }
                    }
                }

                if (open)
                {
                    try
                    {
                        writer5.CloseMapTokensToSourceSpans();
                    }
                    catch (Exception ex)
                    {
                        throw new PdbWritingException(ex);
                    }
                }
            }
        }
Example #3
0
        public override void Visit(IMethodReference methodReference)
        {
            IGenericMethodInstanceReference genericMethodInstanceReference = methodReference.AsGenericMethodInstanceReference;

            if (genericMethodInstanceReference != null)
            {
                this.Visit(genericMethodInstanceReference);
                return;
            }

            if (!alreadySeen.Add(methodReference))
            {
                return;
            }

            // If we have a ref to a varargs method then we always generate an entry in the MethodRef table,
            // even if it is a method in the current module. (Note that we are not *required* to do so if
            // in fact the number of extra arguments passed is zero; in that case we are permitted to use
            // an ordinary method def token. We consistently choose to emit a method ref regardless.)

            IUnitReference definingUnit = PeWriter.GetDefiningUnitReference(methodReference.GetContainingType(Context), Context);

            if (definingUnit != null && ReferenceEquals(definingUnit, this.module) && !methodReference.AcceptsExtraArguments)
            {
                return;
            }

            this.Visit((ITypeMemberReference)methodReference);
            ISpecializedMethodReference specializedMethodReference = methodReference.AsSpecializedMethodReference;

            if (specializedMethodReference != null)
            {
                IMethodReference unspecializedMethodReference = specializedMethodReference.UnspecializedVersion;
                this.Visit(unspecializedMethodReference.GetType(Context));
                this.Visit(unspecializedMethodReference.GetParameters(Context));
                this.Visit(unspecializedMethodReference.ReturnValueCustomModifiers);
            }
            else
            {
                this.Visit(methodReference.GetType(Context));
                this.Visit(methodReference.GetParameters(Context));
                this.Visit(methodReference.ReturnValueCustomModifiers);
            }

            if (methodReference.AcceptsExtraArguments)
            {
                this.Visit(methodReference.ExtraParameters);
            }

            ReserveMethodToken(methodReference);
        }
Example #4
0
        public void SetMetadataEmitter(PeWriter peWriter)
        {
            try
            {
                var instance = (ISymUnmanagedWriter2)Activator.CreateInstance(GetCorSymWriterSxSType());
                instance.Initialize(new PdbMetadataWrapper(peWriter), this.fileName, this.stream, true);

                this.symWriter = instance;
            }
            catch (Exception ex)
            {
                throw new PdbWritingException(ex);
            }
        }
        // The only purpose of this method is to get type name and "is nested" flag, everything else is ignored by the SymWriter.
        // "td" is token returned by GetMethodProps or GetNestedClassProps
        unsafe uint IMetaDataImport.GetTypeDefProps(uint td, IntPtr stringTypeDef, uint cchTypeDef, out uint pchTypeDef, IntPtr pdwTypeDefFlags)
        {
            pchTypeDef = 0;
            if (td == 0)
            {
                return(0);
            }

            // The typeDef name should be fully qualified
            ITypeDefinition t = this.writer.GetTypeDefinition(td);
            string          typeDefName;

            if (this.lastTypeDef == td)
            {
                typeDefName = this.lastTypeDefName;
            }
            else
            {
                typeDefName = PeWriter.GetMangledName((INamedTypeReference)t);

                INamespaceTypeDefinition namespaceTypeDef;

                if ((namespaceTypeDef = t.AsNamespaceTypeDefinition(this.writer.Context)) != null)
                {
                    typeDefName = CodeAnalysis.MetadataHelpers.BuildQualifiedName(namespaceTypeDef.NamespaceName, typeDefName);
                }

                this.lastTypeDef     = td;
                this.lastTypeDefName = typeDefName;
            }

            pchTypeDef = (uint)typeDefName.Length;
            if (pchTypeDef >= cchTypeDef)
            {
                pchTypeDef = cchTypeDef - 1;
            }

            char *pointerTypeDef = (char *)stringTypeDef.ToPointer();

            for (int i = 0; i < pchTypeDef; i++)
            {
                *(pointerTypeDef + i) = typeDefName[i];
            }

            *(pointerTypeDef + pchTypeDef) = (char)0;
            uint *pointerFlags = (uint *)pdwTypeDefFlags.ToPointer();

            *pointerFlags = this.writer.GetTypeDefFlags(t.GetResolvedType(this.writer.Context));
            return(0);
        }
Example #6
0
        public override void Visit(IFieldReference fieldReference)
        {
            if (!alreadySeen.Add(fieldReference))
            {
                return;
            }

            IUnitReference /*?*/ definingUnit = PeWriter.GetDefiningUnitReference(fieldReference.GetContainingType(Context), Context);

            if (definingUnit != null && ReferenceEquals(definingUnit, this.module))
            {
                return;
            }

            this.Visit((ITypeMemberReference)fieldReference);
            this.Visit(fieldReference.GetType(Context));
            ReserveFieldToken(fieldReference);
        }
Example #7
0
        public static bool WritePeToStream(
            EmitContext context,
            CommonMessageProvider messageProvider,
            Func<Stream> getPeStream,
            PdbWriter nativePdbWriterOpt,
            string pdbPathOpt,
            bool allowMissingMethodBodies,
            bool deterministic,
            CancellationToken cancellationToken)
        {
            // If PDB writer is given, we have to have PDB path.
            Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null);

            var peWriter = new PeWriter(context.Module, pdbPathOpt, deterministic);
            var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, deterministic, cancellationToken);

            return peWriter.WritePeToStream(mdWriter, getPeStream, nativePdbWriterOpt);
        }
Example #8
0
        private void SerializeNamespaceScopeMetadata(IMethodBody methodBody, ArrayBuilder <MemoryStream> customDebugInfo)
        {
            if (ShouldForwardToPreviousMethodWithUsingInfo(methodBody))
            {
                Debug.Assert(!ReferenceEquals(this.previousMethodBodyWithUsingInfo, methodBody));
                SerializeReferenceToPreviousMethodWithUsingInfo(customDebugInfo);
                return;
            }

            MemoryStream  customMetadata = new MemoryStream();
            List <ushort> usingCounts    = new List <ushort>();
            BinaryWriter  cmw            = new BinaryWriter(customMetadata);

            foreach (NamespaceScope namespaceScope in methodBody.NamespaceScopes)
            {
                usingCounts.Add((ushort)namespaceScope.UsedNamespaces.Length);
            }

            // ACASEY: This originally wrote (uint)12, (ushort)1, (ushort)0 in the
            // case where usingCounts was empty, but I'm not sure why.
            if (usingCounts.Count > 0)
            {
                uint streamLength = 0;
                cmw.WriteByte(4); // version
                cmw.WriteByte(0); // kind: UsingInfo
                cmw.Align(4);

                cmw.WriteUint(streamLength = PeWriter.Aligned((uint)usingCounts.Count * 2 + 10, 4));
                cmw.WriteUshort((ushort)usingCounts.Count);
                foreach (ushort uc in usingCounts)
                {
                    cmw.WriteUshort(uc);
                }

                cmw.Align(4);
                Debug.Assert(streamLength == customMetadata.Length);
                customDebugInfo.Add(customMetadata);
            }

            if (this.methodBodyWithModuleInfo != null && !ReferenceEquals(this.methodBodyWithModuleInfo, methodBody))
            {
                SerializeReferenceToMethodWithModuleInfo(customDebugInfo);
            }
        }
Example #9
0
        public static void WritePeToStream(
            EmitContext context,
            CommonMessageProvider messageProvider,
            Stream peStream,
            PdbWriter nativePdbWriterOpt,
            bool allowMissingMethodBodies,
            bool deterministic,
            CancellationToken cancellationToken)
        {
            var peWriter = new PeWriter(context.Module, nativePdbWriterOpt, deterministic);

            var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, deterministic, cancellationToken);

            if (nativePdbWriterOpt != null)
            {
                nativePdbWriterOpt.SetMetadataEmitter(mdWriter);
            }

            uint entryPointToken;
            peWriter.WritePeToStream(mdWriter, peStream, nativePdbWriterOpt, out entryPointToken);

            if (nativePdbWriterOpt != null)
            {
                if (entryPointToken != 0)
                {
                    nativePdbWriterOpt.SetEntryPoint(entryPointToken);
                }

                var assembly = context.Module.AsAssembly;
                if (assembly != null && assembly.Kind == ModuleKind.WindowsRuntimeMetadata)
                {
                    // Dev12: If compiling to winmdobj, we need to add to PDB source spans of
                    //        all types and members for better error reporting by WinMDExp.
                    nativePdbWriterOpt.WriteDefinitionLocations(context.Module.GetSymbolToLocationMap());
                }
            }
        }
Example #10
0
 internal TypeSpecComparer(PeWriter peWriter)
 {
     this.peWriter = peWriter;
 }
Example #11
0
 internal FullReferenceIndexer(PeWriter peWriter)
     : base(peWriter)
 {
 }
Example #12
0
 internal ReferenceIndexer(PeWriter peWriter)
     : base(peWriter.Context)
 {
     this.peWriter = peWriter;
 }
Example #13
0
 internal MethodSpecComparer(PeWriter peWriter)
 {
     this.peWriter = peWriter;
 }
 internal PdbMetadataWrapper(PeWriter writer)
 {
     this.writer = writer;
 }
Example #15
0
        unsafe uint IMetaDataImport.GetTypeDefProps(uint td, IntPtr szTypeDef, uint cchTypeDef, out uint pchTypeDef, IntPtr pdwTypeDefFlags)
        {
            pchTypeDef = 0;
            if (td == 0)
            {
                return(0);
            }
            ITypeReference t = null;

            if ((td & 0xFF000000) == 0x1B000000)
            {
                t = this.writer.typeSpecList[(int)(td & 0xFFFFFF) - 1];
                IGenericTypeInstanceReference gt = t as IGenericTypeInstanceReference;
                if (gt != null)
                {
                    t = gt.GenericType;
                }
            }
            else
            {
                t = this.writer.typeDefList[(int)(td & 0xFFFFFF) - 1];
            }
            string tName;
            uint   parentToken = 0;

            if (this.lastTd == td)
            {
                tName       = this.lastTName;
                parentToken = this.lastParentToken;
            }
            else
            {
                tName          = TypeHelper.GetTypeName(t, NameFormattingOptions.UseGenericTypeNameSuffix | NameFormattingOptions.OmitContainingType);
                this.lastTd    = td;
                this.lastTName = tName;
                ITypeReference bc = null;
                foreach (ITypeReference baseClassRef in t.ResolvedType.BaseClasses)
                {
                    bc = baseClassRef;
                }
                if (bc != null)
                {
                    parentToken = (uint)this.writer.GetTypeToken(bc);
                }
                this.lastParentToken = parentToken;
            }
            pchTypeDef = (uint)tName.Length;
            if (pchTypeDef >= cchTypeDef)
            {
                pchTypeDef = cchTypeDef - 1;
            }
            char *pTypeDef = (char *)szTypeDef.ToPointer();

            for (int i = 0; i < pchTypeDef; i++)
            {
                *(pTypeDef + i) = tName[i];
            }
            *(pTypeDef + pchTypeDef) = (char)0;
            uint *pFlags = (uint *)pdwTypeDefFlags.ToPointer();

            *(pFlags) = PeWriter.GetTypeDefFlags(t.ResolvedType);
            return(parentToken);
        }
Example #16
0
 internal ReferenceIndexer(PeWriter peWriter)
     : base(peWriter.Context)
 {
     this.peWriter = peWriter;
 }
Example #17
0
        static int RealMain(string[] args)
        {
            int errorReturnValue = -1;

            #region Check options

            ILMerge.options = new ILMergeOptions();
            options.Parse(args);

            if (options.HelpRequested)
            {
                options.PrintOptions("");
                return(errorReturnValue);
            }
            if (options.HasErrors)
            {
                options.PrintErrorsAndExit(Console.Out);
            }

            if (options.breakIntoDebugger)
            {
                System.Diagnostics.Debugger.Break();
            }
            #endregion

            Version version = null;
            if (options.version != null)
            {
                TryGetVersionNumber(options.version, out version);
            }

            using (var host = new ILMergeHost(options.libpaths)) {
                if (options.libpaths != null)
                {
                    foreach (var libpath in options.libpaths)
                    {
                        host.AddLibPath(libpath);
                    }
                }

                Assembly /*?*/ primaryAssembly = null;
                var            modules         = new List <Module>();
                var            unit2SourceLocationProviderMap = new Dictionary <IUnit, ISourceLocationProvider>();
                var            unit2LocalScopeProviderMap     = new Dictionary <IUnit, ILocalScopeProvider>();
                try {
                    for (int i = 0; i < options.GeneralArguments.Count; i++)
                    {
                        var unitName = options.GeneralArguments[i];
                        var u        = host.LoadUnitFrom(unitName) as IModule;
                        if (i == 0)
                        {
                            IAssembly /*?*/ assembly = u as IAssembly;
                            if (assembly == null || assembly is Dummy)
                            {
                                Console.WriteLine(unitName + " is not a PE file containing a CLR assembly, or an error occurred when loading it.");
                                return(errorReturnValue);
                            }
                            // Use (the copy of) the first input assembly as the merged assembly!
                            primaryAssembly = new MetadataDeepCopier(host).Copy(assembly);
                        }
                        else
                        {
                            var copier        = new MetadataDeepCopier(host, primaryAssembly);
                            var mutableModule = copier.Copy(u);
                            modules.Add(mutableModule);
                        }
                        PdbReader /*?*/ pdbReader = null;
                        string          pdbFile   = Path.ChangeExtension(u.Location, "pdb");
                        if (File.Exists(pdbFile))
                        {
                            using (var pdbStream = File.OpenRead(pdbFile)) {
                                pdbReader = new PdbReader(pdbStream, host);
                            }
                            unit2SourceLocationProviderMap.Add(u, pdbReader);
                            unit2LocalScopeProviderMap.Add(u, pdbReader);
                        }
                        else
                        {
                            Console.WriteLine("Could not load the PDB file for the unit '" + u.Name.Value + "' . Proceeding anyway.");
                            unit2SourceLocationProviderMap.Add(u, null);
                        }
                    }

                    //PdbWriter/*?*/ pdbWriter = null;

                    RewriteUnitReferences renamer = new RewriteUnitReferences(host, modules, options);
                    renamer.targetAssembly           = primaryAssembly;
                    renamer.originalAssemblyIdentity = primaryAssembly.AssemblyIdentity;

                    int totalNumberOfTypes = primaryAssembly.AllTypes.Count;

                    #region Pass 1: Mutate each input module (including the primary assembly) so everything is re-parented to the merged assembly
                    renamer.RewriteChildren(primaryAssembly);
                    for (int i = 0, n = modules.Count; i < n; i++)
                    {
                        var mutableModule = modules[i];
                        // call Rewrite and not RewriteChildren so dynamic dispatch can call the right rewriter method
                        // otherwise, it just rewrites it as a module, not whatever subtype it is.
                        renamer.Rewrite(mutableModule);
                        // However, the rewriter does *not* rewrite parents. So need to re-parent the root unit namespace
                        // of the mutable assembly so it points to the merged assembly. Otherwise, interning (among other
                        // things) will not work correctly.
                        var rootUnitNs = (RootUnitNamespace)mutableModule.UnitNamespaceRoot;
                        rootUnitNs.Unit     = primaryAssembly;
                        totalNumberOfTypes += mutableModule.AllTypes.Count;
                    }
                    #endregion

                    #region Pass 2: Collect all of the types into the merged assembly

                    var mergedTypes = new List <INamedTypeDefinition>(totalNumberOfTypes);

                    #region Merge together all of the <Module> classes from the input assemblies
                    // TODO: Merge all of the <Module> classes, i.e., type 0 from each of the input assemblies
                    mergedTypes.Add(primaryAssembly.AllTypes[0]);
                    #endregion

                    var internedKeys = new HashSet <string>(); // keep track of all namespace type definitions

                    #region Types from the primary assembly
                    for (int i = 1, n = primaryAssembly.AllTypes.Count; i < n; i++)
                    {
                        var t = primaryAssembly.AllTypes[i];
                        mergedTypes.Add(t);
                        if (t is INamespaceTypeDefinition) // don't care about nested types
                        {
                            var key = TypeHelper.GetTypeName(t, NameFormattingOptions.None);
                            internedKeys.Add(key);
                        }
                    }
                    #endregion

                    #region Types from the other input assemblies, taking care of duplicates

                    for (int i = 0, n = modules.Count; i < n; i++)
                    {
                        var module   = modules[i];
                        var unitName = module.Name.Value;
                        for (int j = 1, m = module.AllTypes.Count; j < m; j++)
                        {
                            var t = module.AllTypes[j];
                            var namespaceTypeDefinition = t as NamespaceTypeDefinition;
                            // duplicates can be only at the top-level: namespace type definitions
                            // if a namespace type definition is unique, then so are all of its nested types
                            if (namespaceTypeDefinition != null)
                            {
                                var typeName = TypeHelper.GetTypeName(namespaceTypeDefinition, NameFormattingOptions.UseGenericTypeNameSuffix);
                                if (internedKeys.Contains(typeName)) // error: duplicate!
                                {
                                    if (!namespaceTypeDefinition.IsPublic || options.allowDup)
                                    {
                                        var newName = String.Format("{0}_from_{1}", namespaceTypeDefinition.Name.Value, unitName);
                                        namespaceTypeDefinition.Name = host.NameTable.GetNameFor(newName);
                                        var newTypeName = TypeHelper.GetTypeName(namespaceTypeDefinition, NameFormattingOptions.UseGenericTypeNameSuffix);
                                        Console.WriteLine("Adding '{0}' as '{1}'", typeName, newTypeName);
                                        internedKeys.Add(typeName);
                                        t = namespaceTypeDefinition;
                                    }
                                    else
                                    {
                                        Console.WriteLine("Error: Duplicate type '{0}'", typeName);
                                        continue; //TODO: set a flag somewhere to force a failure.
                                    }
                                }
                                else
                                {
                                    //Console.WriteLine("Adding '{0}'", typeName);
                                    internedKeys.Add(typeName);
                                }
                            }
                            mergedTypes.Add(t);
                        }
                    }
                    #endregion

                    primaryAssembly.AllTypes = mergedTypes;

                    #endregion

                    CopyResourcesToPrimaryAssembly(primaryAssembly, modules);

                    if (version != null)
                    {
                        primaryAssembly.Version = version;
                    }

                    string outputPath;
                    if (options.output != null)
                    {
                        outputPath = options.output;
                    }
                    else
                    {
                        outputPath = primaryAssembly.Name.Value + Path.GetExtension(options.GeneralArguments[0]) + ".meta";
                    }

                    using (var aggregateSourceLocationProvider = new AggregatingSourceLocationProvider(unit2SourceLocationProviderMap)) {
                        using (var aggregateLocalScopeProvider = new AggregatingLocalScopeProvider(unit2LocalScopeProviderMap)) {
                            using (var peStream = File.Create(outputPath)) {
                                using (var pdbWriter = new PdbWriter(Path.ChangeExtension(outputPath, "pdb"), aggregateSourceLocationProvider)) {
                                    PeWriter.WritePeToStream(primaryAssembly, host, peStream, aggregateSourceLocationProvider, aggregateLocalScopeProvider, pdbWriter);
                                }
                            }
                        }
                    }
                } finally {
                }

                return(0); // success
            }
        }
Example #18
0
        public void WriteDefinitionLocations(PeWriter peWriter, MultiDictionary<Cci.DebugSourceDocument, Cci.DefinitionWithLocation> file2definitions)
        {
            ISymUnmanagedWriter5 writer5 = this.symWriter as ISymUnmanagedWriter5;

            if ((object)writer5 != null)
            {
                // NOTE: ISymUnmanagedWriter5 reports HRESULT = 0x806D000E in case we open and close 
                //       the map without writing any resords with MapTokenToSourceSpan(...)
                bool open = false;

                foreach (var doc in file2definitions.Keys)
                {
                    ISymUnmanagedDocumentWriter docWriter = GetDocumentWriter(doc);
                    foreach (var definition in file2definitions[doc])
                    {
                        if (!open)
                        {
                            try
                            {
                                writer5.OpenMapTokensToSourceSpans();
                            }
                            catch (Exception ex)
                            {
                                throw new PdbWritingException(ex);
                            }

                            open = true;
                        }

                        uint token = peWriter.GetTokenForDefinition(definition.Definition);
                        Debug.Assert(token != 0);

                        try
                        {
                            writer5.MapTokenToSourceSpan(token, docWriter,
                                definition.StartLine + 1, definition.StartColumn + 1, definition.EndLine + 1, definition.EndColumn + 1);
                        }
                        catch (Exception ex)
                        {
                            throw new PdbWritingException(ex);
                        }
                    }
                }

                if (open)
                {
                    try
                    {
                        writer5.CloseMapTokensToSourceSpans();
                    }
                    catch (Exception ex)
                    {
                        throw new PdbWritingException(ex);
                    }
                }
            }
        }
Example #19
0
        public void SetMetadataEmitter(PeWriter peWriter)
        {
            try
            {
                var instance = (ISymUnmanagedWriter2)Activator.CreateInstance(GetCorSymWriterSxSType());
                instance.Initialize(new PdbMetadataWrapper(peWriter), this.fileName, this.stream, true);

                this.symWriter = instance;
            }
            catch (Exception ex)
            {
                throw new PdbWritingException(ex);
            }
        }
Example #20
0
 internal MemberRefComparer(PeWriter peWriter)
 {
     this.peWriter = peWriter;
 }