private void SerializeMethodBodyTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (var row in _methodBodyTable) { writer.WriteReference((uint)_debugHeapsOpt.ResolveBlobIndex(row.SequencePoints), metadataSizes.BlobIndexSize); } }
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); } }
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); } }
private void SerializeStateMachineMethodTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (var row in _stateMachineMethodTable) { writer.WriteReference(row.MoveNextMethod, metadataSizes.MethodDefIndexSize); writer.WriteReference(row.KickoffMethod, metadataSizes.MethodDefIndexSize); } }
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); } }
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); } }
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); } }
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); } }
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; }
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; }
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(); }
private int CalculateMappedFieldDataStreamRva(MetadataSizes metadataSizes) { FillInTextSectionHeader(metadataSizes); Debug.Assert(metadataSizes.MappedFieldDataSize % MetadataWriter.MappedFieldDataAlignment == 0); return (int)(_textSection.RelativeVirtualAddress + _textSection.VirtualSize - metadataSizes.MappedFieldDataSize); }
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; }
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; }
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(); }
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 }; } }
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; }
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; }
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; }
private int ComputeOffsetToImportTable(MetadataSizes metadataSizes) { // TODO: add size of unmanaged export stubs (when and if these are ever supported). return ComputeOffsetToDebugTable(metadataSizes) + ComputeSizeOfDebugDirectory(); }
private int ComputeOffsetToDebugTable(MetadataSizes metadataSizes) { return ComputeOffsetToMetadata(metadataSizes.ILStreamSize) + metadataSizes.MetadataSize + metadataSizes.ResourceDataSize + ComputeStrongNameSignatureSize(); // size of strong name hash }
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); } }
private int ComputeSizeOfTextSection(MetadataSizes metadataSizes) { Debug.Assert(metadataSizes.MappedFieldDataSize % MetadataWriter.MappedFieldDataAlignment == 0); return CalculateOffsetToMappedFieldDataStream(metadataSizes) + metadataSizes.MappedFieldDataSize; }
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; }
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 ); } }
private int CalculateMappedFieldDataStreamRva(int textSectionRva, MetadataSizes metadataSizes) { return textSectionRva + CalculateOffsetToMappedFieldDataStream(metadataSizes); }
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); }
private int ComputeOffsetToImportTable(MetadataSizes metadataSizes) { return ComputeOffsetToDebugTable(metadataSizes) + ComputeSizeOfDebugDirectory(); }
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(); }
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)); }
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); } }