コード例 #1
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 (_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;
            }
        }
コード例 #2
0
ファイル: PEBuilder.cs プロジェクト: zlphoenix/roslyn
        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);
        }
コード例 #3
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);
            }
        }
コード例 #4
0
ファイル: R2RPEBuilder.cs プロジェクト: zaccharles/corert
        /// <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);
        }
コード例 #5
0
ファイル: R2RPEBuilder.cs プロジェクト: rinku2028/runtime
        /// <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);
        }
コード例 #6
0
ファイル: PEBuilderTests.cs プロジェクト: mauriciolsrj/corefx
        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);
        }
コード例 #7
0
        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);
        }
コード例 #8
0
ファイル: PEBuilder.cs プロジェクト: zlphoenix/roslyn
        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);
        }
コード例 #9
0
ファイル: PeWriter.cs プロジェクト: Rookieek/roslyn
        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;
        }
コード例 #10
0
        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);
                });
            }
        }
コード例 #11
0
 /// <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);
 }
コード例 #12
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);
        }