Beispiel #1
0
 private void SerializeMethodBodyTable(BlobBuilder writer, MetadataSizes metadataSizes)
 {
     foreach (var row in _methodBodyTable)
     {
         writer.WriteReference((uint)_debugHeapsOpt.ResolveBlobIndex(row.SequencePoints), metadataSizes.BlobIndexSize);
     }
 }
Beispiel #2
0
 private void SerializeLocalConstantTable(BlobBuilder writer, MetadataSizes metadataSizes)
 {
     foreach (var row in _localConstantTable)
     {
         writer.WriteReference((uint)_debugHeapsOpt.ResolveStringIndex(row.Name), metadataSizes.StringIndexSize);
         writer.WriteReference((uint)_debugHeapsOpt.ResolveBlobIndex(row.Signature), metadataSizes.BlobIndexSize);
     }
 }
Beispiel #3
0
 private void SerializeImportScopeTable(BlobBuilder writer, MetadataSizes metadataSizes)
 {
     foreach (var row in _importScopeTable)
     {
         writer.WriteReference(row.Parent, metadataSizes.ImportScopeIndexSize);
         writer.WriteReference((uint)_debugHeapsOpt.ResolveBlobIndex(row.Imports), metadataSizes.BlobIndexSize);
     }
 }
Beispiel #4
0
 private void SerializeStateMachineMethodTable(BlobBuilder writer, MetadataSizes metadataSizes)
 {
     foreach (var row in _stateMachineMethodTable)
     {
         writer.WriteReference(row.MoveNextMethod, metadataSizes.MethodDefIndexSize);
         writer.WriteReference(row.KickoffMethod, metadataSizes.MethodDefIndexSize);
     }
 }
Beispiel #5
0
 private void SerializeLocalVariableTable(BlobBuilder writer, MetadataSizes metadataSizes)
 {
     foreach (var row in _localVariableTable)
     {
         writer.WriteUInt16(row.Attributes);
         writer.WriteUInt16(row.Index);
         writer.WriteReference((uint)_debugHeapsOpt.ResolveStringIndex(row.Name), metadataSizes.StringIndexSize);
     }
 }
Beispiel #6
0
 private void SerializeDocumentTable(BlobBuilder writer, MetadataSizes metadataSizes)
 {
     foreach (var row in _documentTable)
     {
         writer.WriteReference((uint)_debugHeapsOpt.ResolveBlobIndex(row.Name), metadataSizes.BlobIndexSize);
         writer.WriteReference(row.HashAlgorithm, metadataSizes.GuidIndexSize);
         writer.WriteReference((uint)_debugHeapsOpt.ResolveBlobIndex(row.Hash), metadataSizes.BlobIndexSize);
         writer.WriteReference(row.Language, metadataSizes.GuidIndexSize);
     }
 }
Beispiel #7
0
        private void SerializeCustomDebugInformationTable(BlobBuilder writer, MetadataSizes metadataSizes)
        {
            // sort by Parent, Kind
            _customDebugInformationTable.Sort(CustomDebugInformationRowComparer.Instance);

            foreach (var row in _customDebugInformationTable)
            {
                writer.WriteReference(row.Parent, metadataSizes.HasCustomDebugInformationSize);
                writer.WriteReference(row.Kind, metadataSizes.GuidIndexSize);
                writer.WriteReference((uint)_debugHeapsOpt.ResolveBlobIndex(row.Value), metadataSizes.BlobIndexSize);
            }
        }
Beispiel #8
0
 private void SerializeLocalScopeTable(BlobBuilder writer, MetadataSizes metadataSizes)
 {
     foreach (var row in _localScopeTable)
     {
         writer.WriteReference(row.Method, metadataSizes.MethodDefIndexSize);
         writer.WriteReference(row.ImportScope, metadataSizes.ImportScopeIndexSize);
         writer.WriteReference(row.VariableList, metadataSizes.LocalVariableIndexSize);
         writer.WriteReference(row.ConstantList, metadataSizes.LocalConstantIndexSize);
         writer.WriteUInt32(row.StartOffset);
         writer.WriteUInt32(row.Length);
     }
 }
Beispiel #9
0
 private uint ComputeOffsetToDebugTable(MetadataSizes metadataSizes)
 {
     uint result = this.ComputeOffsetToMetadata(metadataSizes.ILStreamSize);
     result += (uint)metadataSizes.MetadataSize;
     result += (uint)metadataSizes.ResourceDataSize;
     result += this.ComputeStrongNameSignatureSize(); // size of strong name hash
     return result;
 }
Beispiel #10
0
 private uint ComputeOffsetToImportTable(MetadataSizes metadataSizes)
 {
     uint result = this.ComputeOffsetToDebugTable(metadataSizes);
     result += this.ComputeSizeOfDebugTable(result);
     result += 0; // TODO: size of unmanaged export stubs (when and if these are ever supported).
     return result;
 }
Beispiel #11
0
        private readonly static byte[] s_zeroStamp = new byte[4]; // four bytes of zero

        /// <summary>
        /// Write the entire "Debug Directory (Image Only)" along with data that it points to.
        /// </summary>
        private void WriteDebugTable(Stream peStream, SectionHeader textSection, ContentId nativePdbContentId, ContentId portablePdbContentId, MetadataSizes metadataSizes)
        {
            int tableSize = ImageDebugDirectoryBaseSize;
            Debug.Assert(tableSize != 0);
            Debug.Assert(nativePdbContentId.IsDefault || portablePdbContentId.IsDefault);
            Debug.Assert(!EmitPdb || (nativePdbContentId.IsDefault ^ portablePdbContentId.IsDefault));

            var writer = PooledBlobBuilder.GetInstance();

            int dataSize = ComputeSizeOfDebugDirectoryData();
            if (this.EmitPdb)
            {
                const int IMAGE_DEBUG_TYPE_CODEVIEW = 2; // from PE spec
                uint dataOffset = (uint)(ComputeOffsetToDebugTable(metadataSizes) + tableSize);
                WriteDebugTableEntry(writer,
                    stamp: nativePdbContentId.Stamp ?? portablePdbContentId.Stamp,
                    version: portablePdbContentId.IsDefault ? (uint)0 : ('P' << 24 | 'M' << 16 | 0x01 << 8 | 0x00),
                    debugType: IMAGE_DEBUG_TYPE_CODEVIEW,
                    sizeOfData: (uint)dataSize,
                    addressOfRawData: (uint)textSection.RelativeVirtualAddress + dataOffset, // RVA of the data
                    pointerToRawData: (uint)textSection.PointerToRawData + dataOffset); // position of the data in the PE stream
            }

            if (_deterministic)
            {
                const int IMAGE_DEBUG_TYPE_NO_TIMESTAMP = 16; // from PE spec
                WriteDebugTableEntry(writer,
                    stamp: s_zeroStamp,
                    version: 0,
                    debugType: IMAGE_DEBUG_TYPE_NO_TIMESTAMP,
                    sizeOfData: 0,
                    addressOfRawData: 0,
                    pointerToRawData: 0);
            }

            // We should now have written all and precisely the data we said we'd write for the table entries.
            Debug.Assert(writer.Count == tableSize);

            // ====================
            // The following is additional data beyond the debug directory at the offset `dataOffset`
            // pointed to by the ImageDebugTypeCodeView entry.

            if (EmitPdb)
            {
                writer.WriteByte((byte)'R');
                writer.WriteByte((byte)'S');
                writer.WriteByte((byte)'D');
                writer.WriteByte((byte)'S');

                // PDB id:
                writer.WriteBytes(nativePdbContentId.Guid ?? portablePdbContentId.Guid);

                // age
                writer.WriteUInt32(PdbWriter.Age);

                // UTF-8 encoded zero-terminated path to PDB
                int pathStart = writer.Position;
                writer.WriteUTF8(_pdbPathOpt, allowUnpairedSurrogates: true);
                writer.WriteByte(0);

                // padding:
                writer.WriteBytes(0, Math.Max(0, _minPdbPath - (writer.Position - pathStart)));
            }

            // We should now have written all and precisely the data we said we'd write for the table and its data.
            Debug.Assert(writer.Count == tableSize + dataSize);

            writer.WriteContentTo(peStream);
            writer.Free();
        }
Beispiel #12
0
        private int CalculateMappedFieldDataStreamRva(MetadataSizes metadataSizes)
        {
            FillInTextSectionHeader(metadataSizes);

            Debug.Assert(metadataSizes.MappedFieldDataSize % MetadataWriter.MappedFieldDataAlignment == 0);
            return (int)(_textSection.RelativeVirtualAddress + _textSection.VirtualSize - metadataSizes.MappedFieldDataSize);
        }
Beispiel #13
0
        private int ComputeOffsetToDebugTable(MetadataSizes metadataSizes)
        {
            Debug.Assert(metadataSizes.MetadataSize % 4 == 0);
            Debug.Assert(metadataSizes.ResourceDataSize % 4 == 0);

            return
                ComputeOffsetToMetadata(metadataSizes.ILStreamSize) +
                metadataSizes.MetadataSize +
                metadataSizes.ResourceDataSize +
                metadataSizes.StrongNameSignatureSize;
        }
Beispiel #14
0
        private int CalculateOffsetToMappedFieldDataStream(MetadataSizes metadataSizes)
        {
            int result = ComputeOffsetToImportTable(metadataSizes);

            if (_properties.RequiresStartupStub)
            {
                result += SizeOfImportTable + SizeOfNameTable;
                result = BitArithmeticUtilities.Align(result, _is32bit ? 4 : 8); //optional padding to make startup stub's target address align on word or double word boundary
                result += SizeOfRuntimeStartupStub;
            }

            return result;
        }
Beispiel #15
0
        private void WriteDebugTable(Stream peStream, SectionHeader textSection, ContentId nativePdbContentId, ContentId portablePdbContentId, MetadataSizes metadataSizes)
        {
            Debug.Assert(nativePdbContentId.IsDefault ^ portablePdbContentId.IsDefault);

            var writer = PooledBlobBuilder.GetInstance();

            // characteristics:
            writer.WriteUInt32(0);

            // PDB stamp & version
            if (portablePdbContentId.IsDefault)
            {
                writer.WriteBytes(nativePdbContentId.Stamp);
                writer.WriteUInt32(0);
            }
            else
            {
                writer.WriteBytes(portablePdbContentId.Stamp);
                writer.WriteUInt32('P' << 24 | 'M' << 16 | 0x00 << 8 | 0x01);
            }
            
            // type: 
            const int ImageDebugTypeCodeView = 2;
            writer.WriteUInt32(ImageDebugTypeCodeView);

            // size of data:
            writer.WriteUInt32((uint)ComputeSizeOfDebugDirectoryData());

            uint dataOffset = (uint)ComputeOffsetToDebugTable(metadataSizes) + ImageDebugDirectoryBaseSize;

            // PointerToRawData (RVA of the data):
            writer.WriteUInt32((uint)textSection.RelativeVirtualAddress + dataOffset);

            // AddressOfRawData (position of the data in the PE stream):
            writer.WriteUInt32((uint)textSection.PointerToRawData + dataOffset);

            writer.WriteByte((byte)'R');
            writer.WriteByte((byte)'S');
            writer.WriteByte((byte)'D');
            writer.WriteByte((byte)'S');

            // PDB id:
            writer.WriteBytes(nativePdbContentId.Guid ?? portablePdbContentId.Guid);

            // age
            writer.WriteUInt32(PdbWriter.Age);

            // UTF-8 encoded zero-terminated path to PDB
            writer.WriteUTF8(_pdbPathOpt, allowUnpairedSurrogates: true);
            writer.WriteByte(0);

            writer.WriteContentTo(peStream);
            writer.Free();
        }
Beispiel #16
0
        private void FillInTextSectionHeader(MetadataSizes metadataSizes)
        {
            if (_textSection == null)
            {
                uint sizeOfPeHeaders = (uint)ComputeSizeOfPeHeaders();
                uint sizeOfTextSection = (uint)ComputeSizeOfTextSection(metadataSizes);

                _textSection = new SectionHeader
                {
                    Characteristics = 0x60000020, // section is read + execute + code 
                    Name = ".text",
                    NumberOfLinenumbers = 0,
                    NumberOfRelocations = 0,
                    PointerToLinenumbers = 0,
                    PointerToRawData = BitArithmeticUtilities.Align(sizeOfPeHeaders, _module.FileAlignment),
                    PointerToRelocations = 0,
                    RelativeVirtualAddress = BitArithmeticUtilities.Align(sizeOfPeHeaders, 0x2000),
                    SizeOfRawData = BitArithmeticUtilities.Align(sizeOfTextSection, _module.FileAlignment),
                    VirtualSize = sizeOfTextSection
                };
            }
        }
Beispiel #17
0
        private void FillInNtHeader(MetadataSizes metadataSizes, int mappedFieldDataStreamRva)
        {
            bool use32bitAddresses = !_module.Requires64bits;
            NtHeader ntHeader = _ntHeader;
            ntHeader.AddressOfEntryPoint = _emitRuntimeStartupStub ? (uint)mappedFieldDataStreamRva - (use32bitAddresses ? 6u : 10u) : 0;
            ntHeader.BaseOfCode = _textSection.RelativeVirtualAddress;
            ntHeader.BaseOfData = _rdataSection.RelativeVirtualAddress;
            ntHeader.PointerToSymbolTable = 0;
            ntHeader.SizeOfCode = _textSection.SizeOfRawData;
            ntHeader.SizeOfInitializedData = _rdataSection.SizeOfRawData + _coverSection.SizeOfRawData + _sdataSection.SizeOfRawData + _tlsSection.SizeOfRawData + _resourceSection.SizeOfRawData + _relocSection.SizeOfRawData;
            ntHeader.SizeOfHeaders = BitArithmeticUtilities.Align(this.ComputeSizeOfPeHeaders(), _module.FileAlignment);
            ntHeader.SizeOfImage = BitArithmeticUtilities.Align(_relocSection.RelativeVirtualAddress + _relocSection.VirtualSize, 0x2000);
            ntHeader.SizeOfUninitializedData = 0;

            // In the PE File Header this is a "Time/Date Stamp" whose description is "Time and date
            // the file was created in seconds since January 1st 1970 00:00:00 or 0"
            // However, when we want to make it deterministic we fill it in (later) with bits from the hash of the full PE file.
            ntHeader.TimeDateStamp = _deterministic ? 0 : (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;

            ntHeader.ImportAddressTable.RelativeVirtualAddress = (_emitRuntimeStartupStub) ? _textSection.RelativeVirtualAddress : 0;
            ntHeader.ImportAddressTable.Size = (uint)_sizeOfImportAddressTable;

            ntHeader.CliHeaderTable.RelativeVirtualAddress = _textSection.RelativeVirtualAddress + ntHeader.ImportAddressTable.Size;
            ntHeader.CliHeaderTable.Size = 72;

            ntHeader.ImportTable.RelativeVirtualAddress = _textSection.RelativeVirtualAddress + (uint)ComputeOffsetToImportTable(metadataSizes);

            if (!_emitRuntimeStartupStub)
            {
                ntHeader.ImportTable.Size = 0;
                ntHeader.ImportTable.RelativeVirtualAddress = 0;
            }
            else
            {
                ntHeader.ImportTable.Size = use32bitAddresses ? 66u : 70u;
                ntHeader.ImportTable.Size += 13;  //size of nametable
            }

            ntHeader.BaseRelocationTable.RelativeVirtualAddress = (_emitRuntimeStartupStub) ? _relocSection.RelativeVirtualAddress : 0;
            ntHeader.BaseRelocationTable.Size = _relocSection.VirtualSize;
            ntHeader.BoundImportTable.RelativeVirtualAddress = 0;
            ntHeader.BoundImportTable.Size = 0;
            ntHeader.CertificateTable.RelativeVirtualAddress = 0;
            ntHeader.CertificateTable.Size = 0;
            ntHeader.CopyrightTable.RelativeVirtualAddress = 0;
            ntHeader.CopyrightTable.Size = 0;
            ntHeader.DebugTable.RelativeVirtualAddress = EmitPdb ? _textSection.RelativeVirtualAddress + (uint)ComputeOffsetToDebugTable(metadataSizes) : 0u;
            ntHeader.DebugTable.Size = EmitPdb ? ImageDebugDirectoryBaseSize : 0u; // Only the size of the fixed part of the debug table goes here.
            ntHeader.DelayImportTable.RelativeVirtualAddress = 0;
            ntHeader.DelayImportTable.Size = 0;
            ntHeader.ExceptionTable.RelativeVirtualAddress = 0;
            ntHeader.ExceptionTable.Size = 0;
            ntHeader.ExportTable.RelativeVirtualAddress = 0;
            ntHeader.ExportTable.Size = 0;
            ntHeader.GlobalPointerTable.RelativeVirtualAddress = 0;
            ntHeader.GlobalPointerTable.Size = 0;
            ntHeader.LoadConfigTable.RelativeVirtualAddress = 0;
            ntHeader.LoadConfigTable.Size = 0;
            ntHeader.Reserved.RelativeVirtualAddress = 0;
            ntHeader.Reserved.Size = 0;
            ntHeader.ResourceTable.RelativeVirtualAddress = _resourceSection.SizeOfRawData == 0 ? 0u : _resourceSection.RelativeVirtualAddress;
            ntHeader.ResourceTable.Size = _resourceSection.VirtualSize;
            ntHeader.ThreadLocalStorageTable.RelativeVirtualAddress = _tlsSection.SizeOfRawData == 0 ? 0u : _tlsSection.RelativeVirtualAddress;
            ntHeader.ThreadLocalStorageTable.Size = _tlsSection.SizeOfRawData;
        }
Beispiel #18
0
        private CorHeader CreateCorHeader(MetadataSizes metadataSizes, int entryPointToken)
        {
            CorHeader corHeader = new CorHeader();
            corHeader.CodeManagerTable.RelativeVirtualAddress = 0;
            corHeader.CodeManagerTable.Size = 0;
            corHeader.EntryPointToken = (uint)entryPointToken;
            corHeader.ExportAddressTableJumps.RelativeVirtualAddress = 0;
            corHeader.ExportAddressTableJumps.Size = 0;
            corHeader.Flags = this.GetCorHeaderFlags();
            corHeader.MajorRuntimeVersion = 2;
            corHeader.MetadataDirectory.RelativeVirtualAddress = _textSection.RelativeVirtualAddress + (uint)ComputeOffsetToMetadata(metadataSizes.ILStreamSize);
            corHeader.MetadataDirectory.Size = (uint)metadataSizes.MetadataSize;
            corHeader.MinorRuntimeVersion = 5;
            corHeader.Resources.RelativeVirtualAddress = corHeader.MetadataDirectory.RelativeVirtualAddress + corHeader.MetadataDirectory.Size;
            corHeader.Resources.Size = (uint)metadataSizes.ResourceDataSize;
            corHeader.StrongNameSignature.RelativeVirtualAddress = corHeader.Resources.RelativeVirtualAddress + corHeader.Resources.Size;
            corHeader.StrongNameSignature.Size = (uint)ComputeStrongNameSignatureSize();
            corHeader.VTableFixups.RelativeVirtualAddress = 0;
            corHeader.VTableFixups.Size = 0;

            return corHeader;
        }
Beispiel #19
0
        private int ComputeSizeOfTextSection(MetadataSizes metadataSizes)
        {
            int textSectionLength = this.ComputeOffsetToImportTable(metadataSizes);

            if (_emitRuntimeStartupStub)
            {
                textSectionLength += !_module.Requires64bits ? 66 : 70; //size of import table
                textSectionLength += 14; //size of name table
                textSectionLength = BitArithmeticUtilities.Align(textSectionLength, !_module.Requires64bits ? 4 : 8); //optional padding to make startup stub's target address align on word or double word boundary
                textSectionLength += !_module.Requires64bits ? 8 : 16; //fixed size of runtime startup stub
            }

            Debug.Assert(metadataSizes.MappedFieldDataSize % MetadataWriter.MappedFieldDataAlignment == 0);
            textSectionLength += metadataSizes.MappedFieldDataSize;
            return textSectionLength;
        }
Beispiel #20
0
 private int ComputeOffsetToImportTable(MetadataSizes metadataSizes)
 {
     // TODO: add size of unmanaged export stubs (when and if these are ever supported).
     return
         ComputeOffsetToDebugTable(metadataSizes) +
         ComputeSizeOfDebugDirectory();
 }
Beispiel #21
0
 private int ComputeOffsetToDebugTable(MetadataSizes metadataSizes)
 {
     return
         ComputeOffsetToMetadata(metadataSizes.ILStreamSize) +
         metadataSizes.MetadataSize +
         metadataSizes.ResourceDataSize +
         ComputeStrongNameSignatureSize(); // size of strong name hash
 }
Beispiel #22
0
        private void WriteTextSection(
            Stream peStream,
            SectionHeader textSection,
            int importTableRva,
            int importAddressTableRva,
            int entryPointToken,
            BlobBuilder metadataWriter,
            BlobBuilder ilWriter,
            BlobBuilder mappedFieldDataWriter,
            BlobBuilder managedResourceWriter,
            MetadataSizes metadataSizes,
            ContentId nativePdbContentId,
            ContentId portablePdbContentId,
            out long metadataPosition)
        {
            // TODO: zero out all bytes:
            peStream.Position = textSection.PointerToRawData;

            if (_properties.RequiresStartupStub)
            {
                WriteImportAddressTable(peStream, importTableRva);
            }

            var corHeader = CreateCorHeader(metadataSizes, textSection.RelativeVirtualAddress, entryPointToken);
            WriteCorHeader(peStream, corHeader);

            // IL:
            ilWriter.Align(4);
            ilWriter.WriteContentTo(peStream);

            // metadata:
            metadataPosition = peStream.Position;
            Debug.Assert(metadataWriter.Count % 4 == 0);
            metadataWriter.WriteContentTo(peStream);

            // managed resources:
            Debug.Assert(managedResourceWriter.Count % 4 == 0);
            managedResourceWriter.WriteContentTo(peStream);

            // strong name signature:
            WriteSpaceForHash(peStream, metadataSizes.StrongNameSignatureSize);

            if (EmitPdb)
            {
                WriteDebugTable(peStream, textSection, nativePdbContentId, portablePdbContentId, metadataSizes);
            }

            if (_properties.RequiresStartupStub)
            {
                WriteImportTable(peStream, importTableRva, importAddressTableRva);
                WriteNameTable(peStream);
                WriteRuntimeStartupStub(peStream, importAddressTableRva);
            }

            // mapped field data:            
            mappedFieldDataWriter.WriteContentTo(peStream);

            // TODO: zero out all bytes:
            int alignedPosition = textSection.PointerToRawData + textSection.SizeOfRawData;
            if (peStream.Position != alignedPosition)
            {
                peStream.Position = alignedPosition - 1;
                peStream.WriteByte(0);
            }
        }
Beispiel #23
0
 private int ComputeSizeOfTextSection(MetadataSizes metadataSizes)
 {
     Debug.Assert(metadataSizes.MappedFieldDataSize % MetadataWriter.MappedFieldDataAlignment == 0);
     return CalculateOffsetToMappedFieldDataStream(metadataSizes) + metadataSizes.MappedFieldDataSize;
 }
Beispiel #24
0
        private List<SectionHeader> CreateSectionHeaders(MetadataSizes metadataSizes, int sectionCount)
        {
            var sectionHeaders = new List<SectionHeader>();
            SectionHeader lastSection;
            int sizeOfPeHeaders = ComputeSizeOfPeHeaders(sectionCount);
            int sizeOfTextSection = ComputeSizeOfTextSection(metadataSizes);

            sectionHeaders.Add(lastSection = new SectionHeader(
                characteristics: SectionCharacteristics.MemRead |
                                 SectionCharacteristics.MemExecute |
                                 SectionCharacteristics.ContainsCode,
                name: ".text",
                numberOfLinenumbers: 0,
                numberOfRelocations: 0,
                pointerToLinenumbers: 0,
                pointerToRawData: BitArithmeticUtilities.Align(sizeOfPeHeaders, _properties.FileAlignment),
                pointerToRelocations: 0,
                relativeVirtualAddress: BitArithmeticUtilities.Align(sizeOfPeHeaders, _properties.SectionAlignment),
                sizeOfRawData: BitArithmeticUtilities.Align(sizeOfTextSection, _properties.FileAlignment),
                virtualSize: sizeOfTextSection
            ));

            int resourcesRva = BitArithmeticUtilities.Align(lastSection.RelativeVirtualAddress + lastSection.VirtualSize, _properties.SectionAlignment);
            int sizeOfWin32Resources = this.ComputeSizeOfWin32Resources(resourcesRva);

            if (sizeOfWin32Resources > 0)
            {
                sectionHeaders.Add(lastSection = new SectionHeader(
                    characteristics: SectionCharacteristics.MemRead |
                                     SectionCharacteristics.ContainsInitializedData,
                    name: ResourceSectionName,
                    numberOfLinenumbers: 0,
                    numberOfRelocations: 0,
                    pointerToLinenumbers: 0,
                    pointerToRawData: lastSection.PointerToRawData + lastSection.SizeOfRawData,
                    pointerToRelocations: 0,
                    relativeVirtualAddress: resourcesRva,
                    sizeOfRawData: BitArithmeticUtilities.Align(sizeOfWin32Resources, _properties.FileAlignment),
                    virtualSize: sizeOfWin32Resources
                ));
            }

            if (_properties.RequiresStartupStub)
            {
                var size = (_properties.Requires64bits && !_properties.RequiresAmdInstructionSet) ? 14 : 12; // TODO: constants

                sectionHeaders.Add(lastSection = new SectionHeader(
                    characteristics: SectionCharacteristics.MemRead |
                                     SectionCharacteristics.MemDiscardable |
                                     SectionCharacteristics.ContainsInitializedData,
                    name: RelocationSectionName,
                    numberOfLinenumbers: 0,
                    numberOfRelocations: 0,
                    pointerToLinenumbers: 0,
                    pointerToRawData: lastSection.PointerToRawData + lastSection.SizeOfRawData,
                    pointerToRelocations: 0,
                    relativeVirtualAddress: BitArithmeticUtilities.Align(lastSection.RelativeVirtualAddress + lastSection.VirtualSize, _properties.SectionAlignment),
                    sizeOfRawData: BitArithmeticUtilities.Align(size, _properties.FileAlignment),
                    virtualSize: size));
            }

            Debug.Assert(sectionHeaders.Count == sectionCount);
            return sectionHeaders;
        }
Beispiel #25
0
        private void FillInTextSectionHeader(MetadataSizes metadataSizes)
        {
            if (_textSection == null)
            {
                int sizeOfPeHeaders = ComputeSizeOfPeHeaders();
                int sizeOfTextSection = ComputeSizeOfTextSection(metadataSizes);

                _textSection = new SectionHeader(
                    characteristics: SectionCharacteristics.MemRead | 
                                     SectionCharacteristics.MemExecute | 
                                     SectionCharacteristics.ContainsCode,
                    name: ".text",
                    numberOfLinenumbers: 0,
                    numberOfRelocations: 0,
                    pointerToLinenumbers: 0,
                    pointerToRawData: BitArithmeticUtilities.Align(sizeOfPeHeaders, _properties.FileAlignment),
                    pointerToRelocations: 0,
                    relativeVirtualAddress: BitArithmeticUtilities.Align(sizeOfPeHeaders, 0x2000),
                    sizeOfRawData: BitArithmeticUtilities.Align(sizeOfTextSection, _properties.FileAlignment),
                    virtualSize: sizeOfTextSection
                );
            }
        }
Beispiel #26
0
 private int CalculateMappedFieldDataStreamRva(int textSectionRva, MetadataSizes metadataSizes)
 {
     return textSectionRva + CalculateOffsetToMappedFieldDataStream(metadataSizes);
 }
Beispiel #27
0
        private void WriteTextSection(
            Stream peStream,
            CorHeader corHeader,
            BlobWriter metadataWriter,
            BlobWriter ilStream,
            BlobWriter mappedFieldDataWriter,
            BlobWriter managedResourceWriter,
            MetadataSizes metadataSizes,
            ContentId pdbContentId,
            out long metadataPosition)
        {
            peStream.Position = _textSection.PointerToRawData;
            if (_emitRuntimeStartupStub)
            {
                this.WriteImportAddressTable(peStream);
            }

            WriteCorHeader(peStream, corHeader);
            WriteIL(peStream, ilStream);

            metadataPosition = peStream.Position;
            WriteMetadata(peStream, metadataWriter);

            WriteManagedResources(peStream, managedResourceWriter);
            WriteSpaceForHash(peStream, (int)corHeader.StrongNameSignature.Size);
            WriteDebugTable(peStream, pdbContentId, metadataSizes);

            if (_emitRuntimeStartupStub)
            {
                WriteImportTable(peStream);
                WriteNameTable(peStream);
                WriteRuntimeStartupStub(peStream);
            }

            WriteMappedFieldData(peStream, mappedFieldDataWriter);
        }
Beispiel #28
0
 private int ComputeOffsetToImportTable(MetadataSizes metadataSizes)
 {
     return
         ComputeOffsetToDebugTable(metadataSizes) +
         ComputeSizeOfDebugDirectory();
 }
Beispiel #29
0
        private void WriteDebugTable(Stream peStream, ContentId nativePdbContentId, MetadataSizes metadataSizes)
        {
            if (!EmitPdb)
            {
                return;
            }

            var writer = new BlobWriter();

            // characteristics:
            writer.WriteUint(0);

            // PDB stamp
            writer.WriteBytes(nativePdbContentId.Stamp);

            // version
            writer.WriteUint(0);

            // type: 
            const int ImageDebugTypeCodeView = 2;
            writer.WriteUint(ImageDebugTypeCodeView);

            // size of data:
            writer.WriteUint((uint)ComputeSizeOfDebugDirectoryData());

            uint dataOffset = (uint)ComputeOffsetToDebugTable(metadataSizes) + ImageDebugDirectoryBaseSize;

            // PointerToRawData (RVA of the data):
            writer.WriteUint(_textSection.RelativeVirtualAddress + dataOffset);

            // AddressOfRawData (position of the data in the PE stream):
            writer.WriteUint(_textSection.PointerToRawData + dataOffset);

            writer.WriteByte((byte)'R');
            writer.WriteByte((byte)'S');
            writer.WriteByte((byte)'D');
            writer.WriteByte((byte)'S');

            // PDB id:
            writer.WriteBytes(nativePdbContentId.Guid);

            // age
            writer.WriteUint(PdbWriter.Age);

            // UTF-8 encoded zero-terminated path to PDB
            writer.WriteUTF8(_pdbPathOpt);
            writer.WriteByte(0);

            writer.WriteTo(peStream);
            writer.Free();
        }
Beispiel #30
0
        private CorHeader CreateCorHeader(MetadataSizes metadataSizes, int textSectionRva, int entryPointToken)
        {
            int metadataRva = textSectionRva + ComputeOffsetToMetadata(metadataSizes.ILStreamSize);
            int resourcesRva = metadataRva + metadataSizes.MetadataSize;
            int signatureRva = resourcesRva + metadataSizes.ResourceDataSize;

            return new CorHeader(
                entryPointTokenOrRelativeVirtualAddress: entryPointToken,
                flags: _properties.GetCorHeaderFlags(),
                metadataDirectory: new DirectoryEntry(metadataRva, metadataSizes.MetadataSize),
                resourcesDirectory: new DirectoryEntry(resourcesRva, metadataSizes.ResourceDataSize),
                strongNameSignatureDirectory: new DirectoryEntry(signatureRva, metadataSizes.StrongNameSignatureSize));
        }
Beispiel #31
0
        private void FillInNtHeader(MetadataSizes metadataSizes, int mappedFieldDataStreamRva)
        {
            // In the PE File Header this is a "Time/Date Stamp" whose description is "Time and date
            // the file was created in seconds since January 1st 1970 00:00:00 or 0"
            // However, when we want to make it deterministic we fill it in (later) with bits from the hash of the full PE file.
            int timeStamp = _deterministic ? 0 : (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;

            int textSectionRva = _textSection.RelativeVirtualAddress;
            
            _coffHeader = new CoffHeader(
                machine: (_properties.Machine == 0) ? Machine.I386 : _properties.Machine,
                numberOfSections: GetSectionCount(),
                timeDateStamp: timeStamp,
                pointerToSymbolTable: 0,
                numberOfSymbols: 0,
                sizeOfOptionalHeader: (short)(_is32bit ? 224 : 240), // TODO: constants
                characteristics: _properties.ImageCharacteristics);

            var ntHeader = _ntHeader = new NtHeader();
            ntHeader.Magic = _is32bit ? PEMagic.PE32 : PEMagic.PE32Plus;
            ntHeader.MajorLinkerVersion = _properties.LinkerMajorVersion;
            ntHeader.MinorLinkerVersion = _properties.LinkerMinorVersion;
            ntHeader.AddressOfEntryPoint = _properties.RequiresStartupStub ? mappedFieldDataStreamRva - (_is32bit ? 6 : 10) : 0; // TODO: constants
            ntHeader.BaseOfCode = textSectionRva;
            ntHeader.BaseOfData = _rdataSection.RelativeVirtualAddress;
            ntHeader.ImageBase = _properties.BaseAddress;
            ntHeader.FileAlignment = _properties.FileAlignment;
            ntHeader.MajorSubsystemVersion = _properties.MajorSubsystemVersion;
            ntHeader.MinorSubsystemVersion = _properties.MinorSubsystemVersion;

            ntHeader.Subsystem = _properties.Subsystem;
            ntHeader.DllCharacteristics = _properties.DllCharacteristics;

            ntHeader.SizeOfStackReserve = _properties.SizeOfStackReserve;
            ntHeader.SizeOfStackCommit = _properties.SizeOfStackCommit;
            ntHeader.SizeOfHeapReserve = _properties.SizeOfHeapReserve; 
            ntHeader.SizeOfHeapCommit = _properties.SizeOfHeapCommit;

            ntHeader.SizeOfCode = _textSection.SizeOfRawData;
            ntHeader.SizeOfInitializedData = _rdataSection.SizeOfRawData + _coverSection.SizeOfRawData + _sdataSection.SizeOfRawData + _tlsSection.SizeOfRawData + _resourceSection.SizeOfRawData + _relocSection.SizeOfRawData;
            ntHeader.SizeOfHeaders = BitArithmeticUtilities.Align(ComputeSizeOfPeHeaders(), _properties.FileAlignment);
            ntHeader.SizeOfImage = BitArithmeticUtilities.Align(_relocSection.RelativeVirtualAddress + _relocSection.VirtualSize, 0x2000);
            ntHeader.SizeOfUninitializedData = 0;

            ntHeader.ImportAddressTable = new DirectoryEntry(
                (_properties.RequiresStartupStub) ? textSectionRva : 0,
                _sizeOfImportAddressTable);

            ntHeader.CliHeaderTable = new DirectoryEntry(
                textSectionRva + _sizeOfImportAddressTable,
                size: 72); // TODO: constants

            if (_properties.RequiresStartupStub)
            {
                ntHeader.ImportTable = new DirectoryEntry(
                    textSectionRva + ComputeOffsetToImportTable(metadataSizes),
                    (_is32bit ? 66 : 70) + 13); // TODO: constants
            }

            ntHeader.BaseRelocationTable = new DirectoryEntry(
                (_properties.RequiresStartupStub) ? _relocSection.RelativeVirtualAddress : 0,
                _relocSection.VirtualSize);

            if (EmitPdb)
            {
                // Only the size of the fixed part of the debug table goes here.
                ntHeader.DebugTable = new DirectoryEntry(
                    _textSection.RelativeVirtualAddress + ComputeOffsetToDebugTable(metadataSizes),
                    ImageDebugDirectoryBaseSize);
            }

            if (_resourceSection.SizeOfRawData > 0)
            {
                ntHeader.ResourceTable = new DirectoryEntry(
                    _resourceSection.RelativeVirtualAddress,
                    _resourceSection.VirtualSize);
            }

            if (_tlsSection.SizeOfRawData > 0)
            {
                ntHeader.ThreadLocalStorageTable = new DirectoryEntry(
                   _tlsSection.RelativeVirtualAddress,
                   _tlsSection.SizeOfRawData);
            }
        }