/// <summary> /// Update the PE file directories. Currently this is used to update the export symbol table /// when export symbols have been added to the section builder. /// </summary> /// <param name="directoriesBuilder">PE directory builder to update</param> public void UpdateDirectories(PEDirectoriesBuilder directoriesBuilder) { if (_corHeaderSymbol != null) { SymbolTarget symbolTarget = _symbolMap[_corHeaderSymbol]; Section section = _sections[symbolTarget.SectionIndex]; Debug.Assert(section.RVAWhenPlaced != 0); directoriesBuilder.CorHeaderTable = new DirectoryEntry(section.RVAWhenPlaced + symbolTarget.Offset, _corHeaderSize); } if (_exportDirectoryEntry.Size != 0) { directoriesBuilder.ExportTable = _exportDirectoryEntry; } int relocationTableRVA = directoriesBuilder.BaseRelocationTable.RelativeVirtualAddress; if (relocationTableRVA == 0) { relocationTableRVA = _relocationDirectoryEntry.RelativeVirtualAddress; } directoriesBuilder.BaseRelocationTable = new DirectoryEntry( relocationTableRVA, directoriesBuilder.BaseRelocationTable.Size + _relocationDirectoryEntry.Size); if (_entryPointSymbol != null) { SymbolTarget symbolTarget = _symbolMap[_entryPointSymbol]; Section section = _sections[symbolTarget.SectionIndex]; Debug.Assert(section.RVAWhenPlaced != 0); directoriesBuilder.AddressOfEntryPoint = section.RVAWhenPlaced + symbolTarget.Offset; } }
public void Serialize(BlobBuilder builder, PEDirectoriesBuilder headers, out ContentId contentId) { var serializedSections = SerializeSections(); Blob stampFixup; WritePESignature(builder); WriteCoffHeader(builder, serializedSections, out stampFixup); WritePEHeader(builder, headers, serializedSections); WriteSectionHeaders(builder, serializedSections); builder.Align(FileAlignment); foreach (var section in serializedSections) { builder.LinkSuffix(section.Builder); builder.Align(FileAlignment); } contentId = IdProvider(builder); // patch timestamp in COFF header: var stampWriter = new BlobWriter(stampFixup); stampWriter.WriteBytes(contentId.Stamp); Debug.Assert(stampWriter.RemainingBytes == 0); }
/// <summary> /// Update the PE file directories. Currently this is used to update the export symbol table /// when export symbols have been added to the section builder. /// </summary> /// <param name="directoriesBuilder">PE directory builder to update</param> public void UpdateDirectories(PEDirectoriesBuilder directoriesBuilder) { if (_corHeaderSymbol != null) { SymbolTarget symbolTarget = _symbolMap[_corHeaderSymbol]; Section section = _sections[symbolTarget.SectionIndex]; Debug.Assert(section.RVAWhenPlaced != 0); directoriesBuilder.CorHeaderTable = new DirectoryEntry(section.RVAWhenPlaced + symbolTarget.Offset, _corHeaderSize); } if (_win32ResourcesSymbol != null) { SymbolTarget symbolTarget = _symbolMap[_win32ResourcesSymbol]; Section section = _sections[symbolTarget.SectionIndex]; Debug.Assert(section.RVAWhenPlaced != 0); // Windows has a bug in its resource processing logic that occurs when // 1. A PE file is loaded as a data file // 2. The resource data found in the resources has an RVA which has a magnitude greater than the size of the section which holds the resources // 3. The offset of the start of the resource data from the start of the section is not zero. // // As it is impossible to effect condition 1 in the compiler, and changing condition 2 would require bloating the virtual size of the sections, // instead require that the resource data is located at offset 0 within the section. // We achieve that by sorting the Win32ResourcesNode as the first node. Debug.Assert(symbolTarget.Offset == 0); directoriesBuilder.ResourceTable = new DirectoryEntry(section.RVAWhenPlaced + symbolTarget.Offset, _win32ResourcesSize); } if (_exportDirectoryEntry.Size != 0) { directoriesBuilder.ExportTable = _exportDirectoryEntry; } int relocationTableRVA = directoriesBuilder.BaseRelocationTable.RelativeVirtualAddress; if (relocationTableRVA == 0) { relocationTableRVA = _relocationDirectoryEntry.RelativeVirtualAddress; } directoriesBuilder.BaseRelocationTable = new DirectoryEntry( relocationTableRVA, directoriesBuilder.BaseRelocationTable.Size + _relocationDirectoryEntry.Size); if (_entryPointSymbol != null) { SymbolTarget symbolTarget = _symbolMap[_entryPointSymbol]; Section section = _sections[symbolTarget.SectionIndex]; Debug.Assert(section.RVAWhenPlaced != 0); directoriesBuilder.AddressOfEntryPoint = section.RVAWhenPlaced + symbolTarget.Offset; } if (_debugDirectorySymbol != null) { SymbolTarget symbolTarget = _symbolMap[_debugDirectorySymbol]; Section section = _sections[symbolTarget.SectionIndex]; Debug.Assert(section.RVAWhenPlaced != 0); directoriesBuilder.DebugTable = new DirectoryEntry(section.RVAWhenPlaced + symbolTarget.Offset, _debugDirectorySize); } }
/// <summary> /// Copy all directory entries and the address of entry point, relocating them along the way. /// </summary> protected override PEDirectoriesBuilder GetDirectories() { PEDirectoriesBuilder builder = new PEDirectoriesBuilder(); builder.CorHeaderTable = RelocateDirectoryEntry(_peReader.PEHeaders.PEHeader.CorHeaderTableDirectory); if (_directoriesUpdater != null) { _directoriesUpdater(builder); } return(builder); }
/// <summary> /// Copy all directory entries and the address of entry point, relocating them along the way. /// </summary> protected override PEDirectoriesBuilder GetDirectories() { PEDirectoriesBuilder builder = new PEDirectoriesBuilder(); _sectionBuilder.UpdateDirectories(builder); RuntimeFunctionsTableNode runtimeFunctionsTable = _getRuntimeFunctionsTable(); builder.ExceptionTable = new DirectoryEntry( relativeVirtualAddress: _sectionBuilder.GetSymbolRVA(runtimeFunctionsTable), size: runtimeFunctionsTable.TableSize); return(builder); }
private static void WritePEImage(Stream peStream, MetadataBuilder metadataBuilder, BlobBuilder ilBuilder, MethodDefinitionHandle entryPointHandle) { var mappedFieldDataBuilder = new BlobBuilder(); var managedResourceDataBuilder = new BlobBuilder(); var peBuilder = new PEBuilder( machine: 0, sectionAlignment: 0x2000, fileAlignment: 0x200, imageBase: 0x00400000, majorLinkerVersion: 0x30, // (what is ref.emit using?) minorLinkerVersion: 0, majorOperatingSystemVersion: 4, minorOperatingSystemVersion: 0, majorImageVersion: 0, minorImageVersion: 0, majorSubsystemVersion: 4, minorSubsystemVersion: 0, subsystem: Subsystem.WindowsCui, dllCharacteristics: DllCharacteristics.DynamicBase | DllCharacteristics.NxCompatible | DllCharacteristics.NoSeh | DllCharacteristics.TerminalServerAware, imageCharacteristics: entryPointHandle.IsNil ? Characteristics.Dll : Characteristics.ExecutableImage, sizeOfStackReserve: 0x00100000, sizeOfStackCommit: 0x1000, sizeOfHeapReserve: 0x00100000, sizeOfHeapCommit: 0x1000); var peDirectoriesBuilder = new PEDirectoriesBuilder(); peBuilder.AddManagedSections( peDirectoriesBuilder, new TypeSystemMetadataSerializer(metadataBuilder, "v4.0.30319", isMinimalDelta: false), ilBuilder, mappedFieldDataBuilder, managedResourceDataBuilder, nativeResourceSectionSerializer: null, strongNameSignatureSize: 0, entryPoint: entryPointHandle, pdbPathOpt: null, nativePdbContentId: default(ContentId), portablePdbContentId: default(ContentId), corFlags: CorFlags.ILOnly); var peBlob = new BlobBuilder(); ContentId peContentId; peBuilder.Serialize(peBlob, peDirectoriesBuilder, out peContentId); peBlob.WriteContentTo(peStream); }
private void WritePEHeader(BlobBuilder builder, PEDirectoriesBuilder headers, ImmutableArray <SerializedSection> sections) { builder.WriteUInt16((ushort)(Is32Bit ? PEMagic.PE32 : PEMagic.PE32Plus)); builder.WriteByte(MajorLinkerVersion); builder.WriteByte(MinorLinkerVersion); // SizeOfCode: builder.WriteUInt32((uint)SumRawDataSizes(sections, SectionCharacteristics.ContainsCode)); // SizeOfInitializedData: builder.WriteUInt32((uint)SumRawDataSizes(sections, SectionCharacteristics.ContainsInitializedData)); // SizeOfUninitializedData: builder.WriteUInt32((uint)SumRawDataSizes(sections, SectionCharacteristics.ContainsUninitializedData)); // AddressOfEntryPoint: builder.WriteUInt32((uint)headers.AddressOfEntryPoint); // BaseOfCode: int codeSectionIndex = IndexOfSection(sections, SectionCharacteristics.ContainsCode); builder.WriteUInt32((uint)(codeSectionIndex != -1 ? sections[codeSectionIndex].RelativeVirtualAddress : 0)); if (Is32Bit) { // BaseOfData: int dataSectionIndex = IndexOfSection(sections, SectionCharacteristics.ContainsInitializedData); builder.WriteUInt32((uint)(dataSectionIndex != -1 ? sections[dataSectionIndex].RelativeVirtualAddress : 0)); builder.WriteUInt32((uint)ImageBase); } else { builder.WriteUInt64(ImageBase); } // NT additional fields: builder.WriteUInt32((uint)SectionAlignment); builder.WriteUInt32((uint)FileAlignment); builder.WriteUInt16(MajorOperatingSystemVersion); builder.WriteUInt16(MinorOperatingSystemVersion); builder.WriteUInt16(MajorImageVersion); builder.WriteUInt16(MinorImageVersion); builder.WriteUInt16(MajorSubsystemVersion); builder.WriteUInt16(MinorSubsystemVersion); // Win32VersionValue (reserved, should be 0) builder.WriteUInt32(0); // SizeOfImage: var lastSection = sections[sections.Length - 1]; builder.WriteUInt32((uint)BitArithmeticUtilities.Align(lastSection.RelativeVirtualAddress + lastSection.VirtualSize, SectionAlignment)); // SizeOfHeaders: builder.WriteUInt32((uint)BitArithmeticUtilities.Align(ComputeSizeOfPeHeaders(sections.Length, Is32Bit), FileAlignment)); // Checksum (TODO: not supported): builder.WriteUInt32(0); builder.WriteUInt16((ushort)Subsystem); builder.WriteUInt16((ushort)DllCharacteristics); if (Is32Bit) { builder.WriteUInt32((uint)SizeOfStackReserve); builder.WriteUInt32((uint)SizeOfStackCommit); builder.WriteUInt32((uint)SizeOfHeapReserve); builder.WriteUInt32((uint)SizeOfHeapCommit); } else { builder.WriteUInt64(SizeOfStackReserve); builder.WriteUInt64(SizeOfStackCommit); builder.WriteUInt64(SizeOfHeapReserve); builder.WriteUInt64(SizeOfHeapCommit); } // LoaderFlags builder.WriteUInt32(0); // The number of data-directory entries in the remainder of the header. builder.WriteUInt32(16); // directory entries: builder.WriteUInt32((uint)headers.ExportTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.ExportTable.Size); builder.WriteUInt32((uint)headers.ImportTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.ImportTable.Size); builder.WriteUInt32((uint)headers.ResourceTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.ResourceTable.Size); builder.WriteUInt32((uint)headers.ExceptionTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.ExceptionTable.Size); builder.WriteUInt32((uint)headers.CertificateTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.CertificateTable.Size); builder.WriteUInt32((uint)headers.BaseRelocationTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.BaseRelocationTable.Size); builder.WriteUInt32((uint)headers.DebugTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.DebugTable.Size); builder.WriteUInt32((uint)headers.CopyrightTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.CopyrightTable.Size); builder.WriteUInt32((uint)headers.GlobalPointerTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.GlobalPointerTable.Size); builder.WriteUInt32((uint)headers.ThreadLocalStorageTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.ThreadLocalStorageTable.Size); builder.WriteUInt32((uint)headers.LoadConfigTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.LoadConfigTable.Size); builder.WriteUInt32((uint)headers.BoundImportTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.BoundImportTable.Size); builder.WriteUInt32((uint)headers.ImportAddressTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.ImportAddressTable.Size); builder.WriteUInt32((uint)headers.DelayImportTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.DelayImportTable.Size); builder.WriteUInt32((uint)headers.CorHeaderTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.CorHeaderTable.Size); // Reserved, should be 0 builder.WriteUInt64(0); }
public static bool WritePeToStream( EmitContext context, CommonMessageProvider messageProvider, Func<Stream> getPeStream, Func<Stream> getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt, string pdbPathOpt, bool allowMissingMethodBodies, bool isDeterministic, CancellationToken cancellationToken) { // If PDB writer is given, we have to have PDB path. Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null); var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, isDeterministic, getPortablePdbStreamOpt != null, cancellationToken); var properties = context.Module.Properties; nativePdbWriterOpt?.SetMetadataEmitter(mdWriter); // Since we are producing a full assembly, we should not have a module version ID // imposed ahead-of time. Instead we will compute a deterministic module version ID // based on the contents of the generated stream. Debug.Assert(properties.PersistentIdentifier == default(Guid)); var ilBuilder = new BlobBuilder(32 * 1024); var mappedFieldDataBuilder = new BlobBuilder(); var managedResourceBuilder = new BlobBuilder(1024); Blob mvidFixup; mdWriter.BuildMetadataAndIL( nativePdbWriterOpt, ilBuilder, mappedFieldDataBuilder, managedResourceBuilder, out mvidFixup); MethodDefinitionHandle entryPointHandle; MethodDefinitionHandle debugEntryPointHandle; mdWriter.GetEntryPoints(out entryPointHandle, out debugEntryPointHandle); if (!debugEntryPointHandle.IsNil) { nativePdbWriterOpt?.SetEntryPoint((uint)MetadataTokens.GetToken(debugEntryPointHandle)); } if (nativePdbWriterOpt != null) { var assembly = mdWriter.Module.AsAssembly; if (assembly != null && assembly.Kind == OutputKind.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(mdWriter.Module.GetSymbolToLocationMap()); } else { #if DEBUG // validate that all definitions are writable // if same scenario would happen in an winmdobj project nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap()); #endif } } Stream peStream = getPeStream(); if (peStream == null) { return false; } ContentId nativePdbContentId = nativePdbWriterOpt?.GetContentId() ?? default(ContentId); // the writer shall not be used after this point for writing: nativePdbWriterOpt = null; var metadataSerializer = mdWriter.GetTypeSystemMetadataSerializer(); var peBuilder = new PEBuilder( machine: properties.Machine, sectionAlignment: properties.SectionAlignment, fileAlignment: properties.FileAlignment, imageBase: properties.BaseAddress, majorLinkerVersion: properties.LinkerMajorVersion, minorLinkerVersion: properties.LinkerMinorVersion, majorOperatingSystemVersion: 4, minorOperatingSystemVersion: 0, majorImageVersion: 0, minorImageVersion: 0, majorSubsystemVersion: properties.MajorSubsystemVersion, minorSubsystemVersion: properties.MinorSubsystemVersion, subsystem: properties.Subsystem, dllCharacteristics: properties.DllCharacteristics, imageCharacteristics: properties.ImageCharacteristics, sizeOfStackReserve: properties.SizeOfStackReserve, sizeOfStackCommit: properties.SizeOfStackCommit, sizeOfHeapReserve: properties.SizeOfHeapReserve, sizeOfHeapCommit: properties.SizeOfHeapCommit, deterministicIdProvider: isDeterministic ? new Func<BlobBuilder, ContentId>(content => ContentId.FromHash(CryptographicHashProvider.ComputeSha1(content))) : null); ContentId portablePdbContentId; if (mdWriter.EmitStandaloneDebugMetadata) { Debug.Assert(getPortablePdbStreamOpt != null); var debugMetadataBuilder = new BlobBuilder(); var debugMetadataSerializer = mdWriter.GetStandaloneDebugMetadataSerializer(metadataSerializer.MetadataSizes, debugEntryPointHandle); debugMetadataSerializer.SerializeMetadata(debugMetadataBuilder, peBuilder.IdProvider, out portablePdbContentId); // write to Portable PDB stream: Stream portablePdbStream = getPortablePdbStreamOpt(); if (portablePdbStream != null) { debugMetadataBuilder.WriteContentTo(portablePdbStream); } } else { portablePdbContentId = default(ContentId); } var peDirectoriesBuilder = new PEDirectoriesBuilder(); peBuilder.AddManagedSections( peDirectoriesBuilder, metadataSerializer, ilBuilder, mappedFieldDataBuilder, managedResourceBuilder, CreateNativeResourceSectionSerializer(context.Module), CalculateStrongNameSignatureSize(context.Module), entryPointHandle, pdbPathOpt, nativePdbContentId, portablePdbContentId, properties.CorFlags); var peBlob = new BlobBuilder(); ContentId peContentId; peBuilder.Serialize(peBlob, peDirectoriesBuilder, out peContentId); // Patch MVID if (!mvidFixup.IsDefault) { var mvidWriter = new BlobWriter(mvidFixup); mvidWriter.WriteBytes(peContentId.Guid); Debug.Assert(mvidWriter.RemainingBytes == 0); } try { peBlob.WriteContentTo(peStream); } catch (Exception e) when (!(e is OperationCanceledException)) { throw new PeWritingException(e); } return true; }
public static void AddManagedSections( this PEBuilder peBuilder, PEDirectoriesBuilder peDirectoriesBuilder, TypeSystemMetadataSerializer metadataSerializer, BlobBuilder ilStream, BlobBuilder mappedFieldData, BlobBuilder managedResourceData, Action <BlobBuilder, PESectionLocation> nativeResourceSectionSerializer, // opt int strongNameSignatureSize, // TODO MethodDefinitionHandle entryPoint, string pdbPathOpt, // TODO ContentId nativePdbContentId, // TODO ContentId portablePdbContentId, // TODO CorFlags corFlags) { int entryPointAddress = 0; // .text peBuilder.AddSection(".text", SectionCharacteristics.MemRead | SectionCharacteristics.MemExecute | SectionCharacteristics.ContainsCode, location => { var sectionBuilder = new BlobBuilder(); var metadataBuilder = new BlobBuilder(); var metadataSizes = metadataSerializer.MetadataSizes; var textSection = new ManagedTextSection( metadataSizes.MetadataSize, ilStreamSize: ilStream.Count, mappedFieldDataSize: mappedFieldData.Count, resourceDataSize: managedResourceData.Count, strongNameSignatureSize: strongNameSignatureSize, imageCharacteristics: peBuilder.ImageCharacteristics, machine: peBuilder.Machine, pdbPathOpt: pdbPathOpt, isDeterministic: peBuilder.IsDeterministic); int methodBodyStreamRva = location.RelativeVirtualAddress + textSection.OffsetToILStream; int mappedFieldDataStreamRva = location.RelativeVirtualAddress + textSection.CalculateOffsetToMappedFieldDataStream(); metadataSerializer.SerializeMetadata(metadataBuilder, methodBodyStreamRva, mappedFieldDataStreamRva); BlobBuilder debugTableBuilderOpt; if (pdbPathOpt != null || peBuilder.IsDeterministic) { debugTableBuilderOpt = new BlobBuilder(); textSection.WriteDebugTable(debugTableBuilderOpt, location, nativePdbContentId, portablePdbContentId); } else { debugTableBuilderOpt = null; } entryPointAddress = textSection.GetEntryPointAddress(location.RelativeVirtualAddress); textSection.Serialize( sectionBuilder, location.RelativeVirtualAddress, entryPoint.IsNil ? 0 : MetadataTokens.GetToken(entryPoint), corFlags, peBuilder.ImageBase, metadataBuilder, ilStream, mappedFieldData, managedResourceData, debugTableBuilderOpt); peDirectoriesBuilder.AddressOfEntryPoint = entryPointAddress; peDirectoriesBuilder.DebugTable = textSection.GetDebugDirectoryEntry(location.RelativeVirtualAddress); peDirectoriesBuilder.ImportAddressTable = textSection.GetImportAddressTableDirectoryEntry(location.RelativeVirtualAddress); peDirectoriesBuilder.ImportTable = textSection.GetImportTableDirectoryEntry(location.RelativeVirtualAddress); peDirectoriesBuilder.CorHeaderTable = textSection.GetCorHeaderDirectoryEntry(location.RelativeVirtualAddress); return(sectionBuilder); }); // .rsrc if (nativeResourceSectionSerializer != null) { peBuilder.AddSection(".rsrc", SectionCharacteristics.MemRead | SectionCharacteristics.ContainsInitializedData, location => { var sectionBuilder = new BlobBuilder(); nativeResourceSectionSerializer(sectionBuilder, location); peDirectoriesBuilder.ResourceTable = new DirectoryEntry(location.RelativeVirtualAddress, sectionBuilder.Count); return(sectionBuilder); }); } // .reloc if (peBuilder.Machine == Machine.I386 || peBuilder.Machine == 0) { peBuilder.AddSection(".reloc", SectionCharacteristics.MemRead | SectionCharacteristics.MemDiscardable | SectionCharacteristics.ContainsInitializedData, location => { var sectionBuilder = new BlobBuilder(); WriteRelocSection(sectionBuilder, peBuilder.Machine, entryPointAddress); peDirectoriesBuilder.BaseRelocationTable = new DirectoryEntry(location.RelativeVirtualAddress, sectionBuilder.Count); return(sectionBuilder); }); } }
/// <summary> /// Update the PE header directories by setting up the exception directory to point to the runtime functions table. /// This is needed for RtlLookupFunctionEntry / RtlLookupFunctionTable to work. /// </summary> /// <param name="builder">PE header directory builder can be used to override RVA's / sizes of any of the directories</param> private void UpdateDirectories(PEDirectoriesBuilder builder) { builder.ExceptionTable = new DirectoryEntry( relativeVirtualAddress: _sectionBuilder.GetSymbolRVA(_nodeFactory.RuntimeFunctionsTable), size: _nodeFactory.RuntimeFunctionsTable.TableSize); }
public static bool WritePeToStream( EmitContext context, CommonMessageProvider messageProvider, Func <Stream> getPeStream, Func <Stream> getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt, string pdbPathOpt, bool allowMissingMethodBodies, bool isDeterministic, CancellationToken cancellationToken) { // If PDB writer is given, we have to have PDB path. Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null); var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, isDeterministic, getPortablePdbStreamOpt != null, cancellationToken); var properties = context.Module.Properties; nativePdbWriterOpt?.SetMetadataEmitter(mdWriter); // Since we are producing a full assembly, we should not have a module version ID // imposed ahead-of time. Instead we will compute a deterministic module version ID // based on the contents of the generated stream. Debug.Assert(properties.PersistentIdentifier == default(Guid)); var ilBuilder = new BlobBuilder(32 * 1024); var mappedFieldDataBuilder = new BlobBuilder(); var managedResourceBuilder = new BlobBuilder(1024); Blob mvidFixup; mdWriter.BuildMetadataAndIL( nativePdbWriterOpt, ilBuilder, mappedFieldDataBuilder, managedResourceBuilder, out mvidFixup); MethodDefinitionHandle entryPointHandle; MethodDefinitionHandle debugEntryPointHandle; mdWriter.GetEntryPoints(out entryPointHandle, out debugEntryPointHandle); if (!debugEntryPointHandle.IsNil) { nativePdbWriterOpt?.SetEntryPoint((uint)MetadataTokens.GetToken(debugEntryPointHandle)); } if (nativePdbWriterOpt != null) { var assembly = mdWriter.Module.AsAssembly; if (assembly != null && assembly.Kind == OutputKind.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(mdWriter.Module.GetSymbolToLocationMap()); } else { #if DEBUG // validate that all definitions are writable // if same scenario would happen in an winmdobj project nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap()); #endif } } Stream peStream = getPeStream(); if (peStream == null) { return(false); } ContentId nativePdbContentId = nativePdbWriterOpt?.GetContentId() ?? default(ContentId); // the writer shall not be used after this point for writing: nativePdbWriterOpt = null; var metadataSerializer = mdWriter.GetTypeSystemMetadataSerializer(); var peBuilder = new PEBuilder( machine: properties.Machine, sectionAlignment: properties.SectionAlignment, fileAlignment: properties.FileAlignment, imageBase: properties.BaseAddress, majorLinkerVersion: properties.LinkerMajorVersion, minorLinkerVersion: properties.LinkerMinorVersion, majorOperatingSystemVersion: 4, minorOperatingSystemVersion: 0, majorImageVersion: 0, minorImageVersion: 0, majorSubsystemVersion: properties.MajorSubsystemVersion, minorSubsystemVersion: properties.MinorSubsystemVersion, subsystem: properties.Subsystem, dllCharacteristics: properties.DllCharacteristics, imageCharacteristics: properties.ImageCharacteristics, sizeOfStackReserve: properties.SizeOfStackReserve, sizeOfStackCommit: properties.SizeOfStackCommit, sizeOfHeapReserve: properties.SizeOfHeapReserve, sizeOfHeapCommit: properties.SizeOfHeapCommit, deterministicIdProvider: isDeterministic ? new Func <BlobBuilder, ContentId>(content => ContentId.FromHash(CryptographicHashProvider.ComputeSha1(content))) : null); ContentId portablePdbContentId; if (mdWriter.EmitStandaloneDebugMetadata) { Debug.Assert(getPortablePdbStreamOpt != null); var debugMetadataBuilder = new BlobBuilder(); var debugMetadataSerializer = mdWriter.GetStandaloneDebugMetadataSerializer(metadataSerializer.MetadataSizes, debugEntryPointHandle); debugMetadataSerializer.SerializeMetadata(debugMetadataBuilder, peBuilder.IdProvider, out portablePdbContentId); // write to Portable PDB stream: Stream portablePdbStream = getPortablePdbStreamOpt(); if (portablePdbStream != null) { debugMetadataBuilder.WriteContentTo(portablePdbStream); } } else { portablePdbContentId = default(ContentId); } var peDirectoriesBuilder = new PEDirectoriesBuilder(); peBuilder.AddManagedSections( peDirectoriesBuilder, metadataSerializer, ilBuilder, mappedFieldDataBuilder, managedResourceBuilder, CreateNativeResourceSectionSerializer(context.Module), CalculateStrongNameSignatureSize(context.Module), entryPointHandle, pdbPathOpt, nativePdbContentId, portablePdbContentId, properties.CorFlags); var peBlob = new BlobBuilder(); ContentId peContentId; peBuilder.Serialize(peBlob, peDirectoriesBuilder, out peContentId); // Patch MVID if (!mvidFixup.IsDefault) { var mvidWriter = new BlobWriter(mvidFixup); mvidWriter.WriteBytes(peContentId.Guid); Debug.Assert(mvidWriter.RemainingBytes == 0); } try { peBlob.WriteContentTo(peStream); } catch (Exception e) when(!(e is OperationCanceledException)) { throw new PeWritingException(e); } return(true); }