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); } } }
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); } } } }
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); }
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); }
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); }
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); }
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); } }
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()); } } }
internal TypeSpecComparer(PeWriter peWriter) { this.peWriter = peWriter; }
internal FullReferenceIndexer(PeWriter peWriter) : base(peWriter) { }
internal ReferenceIndexer(PeWriter peWriter) : base(peWriter.Context) { this.peWriter = peWriter; }
internal MethodSpecComparer(PeWriter peWriter) { this.peWriter = peWriter; }
internal PdbMetadataWrapper(PeWriter writer) { this.writer = writer; }
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); }
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 } }
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); } } } }
internal MemberRefComparer(PeWriter peWriter) { this.peWriter = peWriter; }