private void SerializeClassLayoutTable(BlobBuilder writer, MetadataSizes metadataSizes) { #if DEBUG for (int i = 1; i < _classLayoutTable.Count; i++) { Debug.Assert(_classLayoutTable[i - 1].Parent < _classLayoutTable[i].Parent); } #endif foreach (ClassLayoutRow classLayout in _classLayoutTable) { writer.WriteUInt16(classLayout.PackingSize); writer.WriteUInt32(classLayout.ClassSize); writer.WriteReference(classLayout.Parent, metadataSizes.TypeDefIndexSize); } }
private void SerializeParamTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (ParamRow param in _paramTable) { writer.WriteUInt16(param.Flags); writer.WriteUInt16(param.Sequence); writer.WriteReference((uint)GetHeapOffset(param.Name), metadataSizes.StringIndexSize); } }
private void SerializeDeclSecurityTable(BlobBuilder writer, MetadataSizes metadataSizes) { // Note: we can sort the table at this point since no other table can reference its rows via RowId or CodedIndex (which would need updating otherwise). // OrderBy performs a stable sort, so multiple attributes with the same parent will be sorted in the order they were added to the table. var ordered = _declSecurityTableNeedsSorting ? (IEnumerable<DeclSecurityRow>)_declSecurityTable.OrderBy((x, y) => (int)x.Parent - (int)y.Parent) : _declSecurityTable; foreach (DeclSecurityRow declSecurity in ordered) { writer.WriteUInt16(declSecurity.Action); writer.WriteReference(declSecurity.Parent, metadataSizes.DeclSecurityCodedIndexSize); writer.WriteReference((uint)GetHeapOffset(declSecurity.PermissionSet), metadataSizes.BlobIndexSize); } }
private void SerializeLocalVariableTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (var row in _localVariableTable) { writer.WriteUInt16(row.Attributes); writer.WriteUInt16(row.Index); writer.WriteReference((uint)GetHeapOffset(row.Name), metadataSizes.StringIndexSize); } }
private void WritePEHeader(BlobBuilder builder, PEDirectoriesBuilder directories, ImmutableArray<SerializedSection> sections) { builder.WriteUInt16((ushort)(Header.Is32Bit ? PEMagic.PE32 : PEMagic.PE32Plus)); builder.WriteByte(Header.MajorLinkerVersion); builder.WriteByte(Header.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)directories.AddressOfEntryPoint); // BaseOfCode: int codeSectionIndex = IndexOfSection(sections, SectionCharacteristics.ContainsCode); builder.WriteUInt32((uint)(codeSectionIndex != -1 ? sections[codeSectionIndex].RelativeVirtualAddress : 0)); if (Header.Is32Bit) { // BaseOfData: int dataSectionIndex = IndexOfSection(sections, SectionCharacteristics.ContainsInitializedData); builder.WriteUInt32((uint)(dataSectionIndex != -1 ? sections[dataSectionIndex].RelativeVirtualAddress : 0)); builder.WriteUInt32((uint)Header.ImageBase); } else { builder.WriteUInt64(Header.ImageBase); } // NT additional fields: builder.WriteUInt32((uint)Header.SectionAlignment); builder.WriteUInt32((uint)Header.FileAlignment); builder.WriteUInt16(Header.MajorOperatingSystemVersion); builder.WriteUInt16(Header.MinorOperatingSystemVersion); builder.WriteUInt16(Header.MajorImageVersion); builder.WriteUInt16(Header.MinorImageVersion); builder.WriteUInt16(Header.MajorSubsystemVersion); builder.WriteUInt16(Header.MinorSubsystemVersion); // Win32VersionValue (reserved, should be 0) builder.WriteUInt32(0); // SizeOfImage: var lastSection = sections[sections.Length - 1]; builder.WriteUInt32((uint)BitArithmetic.Align(lastSection.RelativeVirtualAddress + lastSection.VirtualSize, Header.SectionAlignment)); // SizeOfHeaders: builder.WriteUInt32((uint)BitArithmetic.Align(Header.ComputeSizeOfPeHeaders(sections.Length), Header.FileAlignment)); // Checksum: // Shall be zero for strong name signing. builder.WriteUInt32(0); builder.WriteUInt16((ushort)Header.Subsystem); builder.WriteUInt16((ushort)Header.DllCharacteristics); if (Header.Is32Bit) { builder.WriteUInt32((uint)Header.SizeOfStackReserve); builder.WriteUInt32((uint)Header.SizeOfStackCommit); builder.WriteUInt32((uint)Header.SizeOfHeapReserve); builder.WriteUInt32((uint)Header.SizeOfHeapCommit); } else { builder.WriteUInt64(Header.SizeOfStackReserve); builder.WriteUInt64(Header.SizeOfStackCommit); builder.WriteUInt64(Header.SizeOfHeapReserve); builder.WriteUInt64(Header.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)directories.ExportTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.ExportTable.Size); builder.WriteUInt32((uint)directories.ImportTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.ImportTable.Size); builder.WriteUInt32((uint)directories.ResourceTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.ResourceTable.Size); builder.WriteUInt32((uint)directories.ExceptionTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.ExceptionTable.Size); // Authenticode CertificateTable directory. Shall be zero before the PE is signed. builder.WriteUInt32(0); builder.WriteUInt32(0); builder.WriteUInt32((uint)directories.BaseRelocationTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.BaseRelocationTable.Size); builder.WriteUInt32((uint)directories.DebugTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.DebugTable.Size); builder.WriteUInt32((uint)directories.CopyrightTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.CopyrightTable.Size); builder.WriteUInt32((uint)directories.GlobalPointerTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.GlobalPointerTable.Size); builder.WriteUInt32((uint)directories.ThreadLocalStorageTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.ThreadLocalStorageTable.Size); builder.WriteUInt32((uint)directories.LoadConfigTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.LoadConfigTable.Size); builder.WriteUInt32((uint)directories.BoundImportTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.BoundImportTable.Size); builder.WriteUInt32((uint)directories.ImportAddressTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.ImportAddressTable.Size); builder.WriteUInt32((uint)directories.DelayImportTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.DelayImportTable.Size); builder.WriteUInt32((uint)directories.CorHeaderTable.RelativeVirtualAddress); builder.WriteUInt32((uint)directories.CorHeaderTable.Size); // Reserved, should be 0 builder.WriteUInt64(0); }
private void SerializeMethodSemanticsTable(BlobBuilder writer, MetadataSizes metadataSizes) { // Note: we can sort the table at this point since no other table can reference its rows via RowId or CodedIndex (which would need updating otherwise). // OrderBy performs a stable sort, so multiple attributes with the same parent will be sorted in the order they were added to the table. var ordered = _methodSemanticsTableNeedsSorting ? (IEnumerable<MethodSemanticsRow>)_methodSemanticsTable.OrderBy((x, y) => (int)x.Association - (int)y.Association) : _methodSemanticsTable; foreach (MethodSemanticsRow methodSemantic in ordered) { writer.WriteUInt16(methodSemantic.Semantic); writer.WriteReference(methodSemantic.Method, metadataSizes.MethodDefIndexSize); writer.WriteReference(methodSemantic.Association, metadataSizes.HasSemanticsCodedIndexSize); } }
private void SerializeAssemblyRefTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (AssemblyRefTableRow row in _assemblyRefTable) { writer.WriteUInt16((ushort)row.Version.Major); writer.WriteUInt16((ushort)row.Version.Minor); writer.WriteUInt16((ushort)row.Version.Build); writer.WriteUInt16((ushort)row.Version.Revision); writer.WriteUInt32(row.Flags); writer.WriteReference((uint)GetHeapOffset(row.PublicKeyToken), metadataSizes.BlobIndexSize); writer.WriteReference((uint)GetHeapOffset(row.Name), metadataSizes.StringIndexSize); writer.WriteReference((uint)GetHeapOffset(row.Culture), metadataSizes.StringIndexSize); writer.WriteReference((uint)GetHeapOffset(row.HashValue), metadataSizes.BlobIndexSize); } }
private void SerializeMetadataHeader(BlobBuilder writer) { int startOffset = writer.Position; // signature writer.WriteUInt32(0x424A5342); // major version writer.WriteUInt16(1); // minor version writer.WriteUInt16(1); // reserved writer.WriteUInt32(0); // metadata version length writer.WriteUInt32(MetadataSizes.MetadataVersionPaddedLength); int n = Math.Min(MetadataSizes.MetadataVersionPaddedLength, _metadataVersion.Length); for (int i = 0; i < n; i++) { writer.WriteByte((byte)_metadataVersion[i]); } for (int i = n; i < MetadataSizes.MetadataVersionPaddedLength; i++) { writer.WriteByte(0); } // reserved writer.WriteUInt16(0); // number of streams writer.WriteUInt16((ushort)(5 + (_sizes.IsMinimalDelta ? 1 : 0) + (_sizes.IsStandaloneDebugMetadata ? 1 : 0))); // stream headers int offsetFromStartOfMetadata = _sizes.MetadataHeaderSize; // emit the #Pdb stream first so that only a single page has to be read in order to find out PDB ID if (_sizes.IsStandaloneDebugMetadata) { SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.StandalonePdbStreamSize, "#Pdb", writer); } // Spec: Some compilers store metadata in a #- stream, which holds an uncompressed, or non-optimized, representation of metadata tables; // this includes extra metadata -Ptr tables. Such PE files do not form part of ECMA-335 standard. // // Note: EnC delta is stored as uncompressed metadata stream. SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.MetadataTableStreamSize, (_sizes.IsMetadataTableStreamCompressed ? "#~" : "#-"), writer); SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.GetAlignedHeapSize(HeapIndex.String), "#Strings", writer); SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.GetAlignedHeapSize(HeapIndex.UserString), "#US", writer); SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.GetAlignedHeapSize(HeapIndex.Guid), "#GUID", writer); SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.GetAlignedHeapSize(HeapIndex.Blob), "#Blob", writer); if (_sizes.IsMinimalDelta) { SerializeStreamHeader(ref offsetFromStartOfMetadata, 0, "#JTD", writer); } int endOffset = writer.Position; Debug.Assert(endOffset - startOffset == _sizes.MetadataHeaderSize); }
internal static void WriteConstant(BlobBuilder writer, object?value) { if (value == null) { // The encoding of Type for the nullref value for FieldInit is ELEMENT_TYPE_CLASS with a Value of a 32-bit. writer.WriteUInt32(0); return; } var type = value.GetType(); if (type.GetTypeInfo().IsEnum) { type = Enum.GetUnderlyingType(type); } if (type == typeof(bool)) { writer.WriteBoolean((bool)value); } else if (type == typeof(int)) { writer.WriteInt32((int)value); } else if (type == typeof(string)) { writer.WriteUTF16((string)value); } else if (type == typeof(byte)) { writer.WriteByte((byte)value); } else if (type == typeof(char)) { writer.WriteUInt16((char)value); } else if (type == typeof(double)) { writer.WriteDouble((double)value); } else if (type == typeof(short)) { writer.WriteInt16((short)value); } else if (type == typeof(long)) { writer.WriteInt64((long)value); } else if (type == typeof(sbyte)) { writer.WriteSByte((sbyte)value); } else if (type == typeof(float)) { writer.WriteSingle((float)value); } else if (type == typeof(ushort)) { writer.WriteUInt16((ushort)value); } else if (type == typeof(uint)) { writer.WriteUInt32((uint)value); } else if (type == typeof(ulong)) { writer.WriteUInt64((ulong)value); } else { throw new ArgumentException(SR.Format(SR.InvalidConstantValueOfType, type)); } }
private void WriteCorHeader(BlobBuilder builder, int textSectionRva, int entryPointTokenOrRva, CorFlags corFlags) { const ushort majorRuntimeVersion = 2; const ushort minorRuntimeVersion = 5; int metadataRva = textSectionRva + ComputeOffsetToMetadata(); int resourcesRva = metadataRva + MetadataSize; int signatureRva = resourcesRva + ResourceDataSize; int start = builder.Count; // Size: builder.WriteUInt32(CorHeaderSize); // Version: builder.WriteUInt16(majorRuntimeVersion); builder.WriteUInt16(minorRuntimeVersion); // MetadataDirectory: builder.WriteUInt32((uint)metadataRva); builder.WriteUInt32((uint)MetadataSize); // COR Flags: builder.WriteUInt32((uint)corFlags); // EntryPoint: builder.WriteUInt32((uint)entryPointTokenOrRva); // ResourcesDirectory: builder.WriteUInt32((uint)(ResourceDataSize == 0 ? 0 : resourcesRva)); // 28 builder.WriteUInt32((uint)ResourceDataSize); // StrongNameSignatureDirectory: builder.WriteUInt32((uint)(StrongNameSignatureSize == 0 ? 0 : signatureRva)); // 36 builder.WriteUInt32((uint)StrongNameSignatureSize); // CodeManagerTableDirectory (not supported): builder.WriteUInt32(0); builder.WriteUInt32(0); // VtableFixupsDirectory (not supported): builder.WriteUInt32(0); builder.WriteUInt32(0); // ExportAddressTableJumpsDirectory (not supported): builder.WriteUInt32(0); builder.WriteUInt32(0); // ManagedNativeHeaderDirectory (not supported): builder.WriteUInt32(0); builder.WriteUInt32(0); Debug.Assert(builder.Count - start == CorHeaderSize); Debug.Assert(builder.Count % 4 == 0); }
private void WriteRuntimeStartupStub(BlobBuilder sectionBuilder, int importAddressTableRva, ulong baseAddress) { // entry point code, consisting of a jump indirect to _CorXXXMain if (Is32Bit) { // Write zeros (nops) to pad the entry point code so that the target address is aligned on a 4 byte boundary. // Note that the section is aligned to FileAlignment, which is at least 512, so we can align relatively to the start of the section. sectionBuilder.Align(4); sectionBuilder.WriteUInt16(0); sectionBuilder.WriteByte(0xff); sectionBuilder.WriteByte(0x25); //4 sectionBuilder.WriteUInt32((uint)importAddressTableRva + (uint)baseAddress); //8 } else { // Write zeros (nops) to pad the entry point code so that the target address is aligned on a 8 byte boundary. // Note that the section is aligned to FileAlignment, which is at least 512, so we can align relatively to the start of the section. sectionBuilder.Align(8); sectionBuilder.WriteUInt32(0); sectionBuilder.WriteUInt16(0); sectionBuilder.WriteByte(0xff); sectionBuilder.WriteByte(0x25); //8 sectionBuilder.WriteUInt64((ulong)importAddressTableRva + baseAddress); //16 } }
private static void WriteNameTable(BlobBuilder builder) { int start = builder.Count; foreach (char ch in CorEntryPointDll) { builder.WriteByte((byte)ch); } builder.WriteByte(0); builder.WriteUInt16(0); Debug.Assert(builder.Count - start == SizeOfNameTable); }
private void WriteImportTable(BlobBuilder builder, int importTableRva, int importAddressTableRva) { int start = builder.Count; int ilRVA = importTableRva + 40; int hintRva = ilRVA + (Is32Bit ? 12 : 16); int nameRva = hintRva + 12 + 2; // Import table builder.WriteUInt32((uint)ilRVA); // 4 builder.WriteUInt32(0); // 8 builder.WriteUInt32(0); // 12 builder.WriteUInt32((uint)nameRva); // 16 builder.WriteUInt32((uint)importAddressTableRva); // 20 builder.WriteBytes(0, 20); // 40 // Import Lookup table if (Is32Bit) { builder.WriteUInt32((uint)hintRva); // 44 builder.WriteUInt32(0); // 48 builder.WriteUInt32(0); // 52 } else { builder.WriteUInt64((uint)hintRva); // 48 builder.WriteUInt64(0); // 56 } // Hint table builder.WriteUInt16(0); // Hint 54|58 foreach (char ch in CorEntryPointName) { builder.WriteByte((byte)ch); // 65|69 } builder.WriteByte(0); // 66|70 Debug.Assert(builder.Count - start == SizeOfImportTable); }
private static void WriteSectionHeader(BlobBuilder builder, SerializedSection serializedSection) { if (serializedSection.VirtualSize == 0) { return; } for (int j = 0, m = serializedSection.Name.Length; j < 8; j++) { if (j < m) { builder.WriteByte((byte)serializedSection.Name[j]); } else { builder.WriteByte(0); } } builder.WriteUInt32((uint)serializedSection.VirtualSize); builder.WriteUInt32((uint)serializedSection.RelativeVirtualAddress); builder.WriteUInt32((uint)serializedSection.SizeOfRawData); builder.WriteUInt32((uint)serializedSection.PointerToRawData); // PointerToRelocations (TODO: not supported): builder.WriteUInt32(0); // PointerToLinenumbers (TODO: not supported): builder.WriteUInt32(0); // NumberOfRelocations (TODO: not supported): builder.WriteUInt16(0); // NumberOfLinenumbers (TODO: not supported): builder.WriteUInt16(0); builder.WriteUInt32((uint)serializedSection.Characteristics); }
private void SerializeEventTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (EventRow eventRow in _eventTable) { writer.WriteUInt16(eventRow.EventFlags); writer.WriteReference((uint)GetHeapOffset(eventRow.Name), metadataSizes.StringIndexSize); writer.WriteReference(eventRow.EventType, metadataSizes.TypeDefOrRefCodedIndexSize); } }
internal static void WriteConstant(BlobBuilder writer, object value) { if (value == null) { // The encoding of Type for the nullref value for FieldInit is ELEMENT_TYPE_CLASS with a Value of a 32-bit. writer.WriteUInt32(0); return; } var type = value.GetType(); if (type.GetTypeInfo().IsEnum) { type = Enum.GetUnderlyingType(type); } if (type == typeof(bool)) { writer.WriteBoolean((bool)value); } else if (type == typeof(int)) { writer.WriteInt32((int)value); } else if (type == typeof(string)) { writer.WriteUTF16((string)value); } else if (type == typeof(byte)) { writer.WriteByte((byte)value); } else if (type == typeof(char)) { writer.WriteUInt16((char)value); } else if (type == typeof(double)) { writer.WriteDouble((double)value); } else if (type == typeof(short)) { writer.WriteInt16((short)value); } else if (type == typeof(long)) { writer.WriteInt64((long)value); } else if (type == typeof(sbyte)) { writer.WriteSByte((sbyte)value); } else if (type == typeof(float)) { writer.WriteSingle((float)value); } else if (type == typeof(ushort)) { writer.WriteUInt16((ushort)value); } else if (type == typeof(uint)) { writer.WriteUInt32((uint)value); } else if (type == typeof(ulong)) { writer.WriteUInt64((ulong)value); } else { throw new ArgumentException(SR.Format(SR.InvalidConstantValueOfType, type)); } }
private void SerializePropertyTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (PropertyRow property in _propertyTable) { writer.WriteUInt16(property.PropFlags); writer.WriteReference((uint)GetHeapOffset(property.Name), metadataSizes.StringIndexSize); writer.WriteReference((uint)GetHeapOffset(property.Type), metadataSizes.BlobIndexSize); } }
private void SerializeModuleTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (var moduleRow in _moduleTable) { writer.WriteUInt16(moduleRow.Generation); writer.WriteReference((uint)GetHeapOffset(moduleRow.Name), metadataSizes.StringIndexSize); writer.WriteReference((uint)GetHeapOffset(moduleRow.ModuleVersionId), metadataSizes.GuidIndexSize); writer.WriteReference((uint)GetHeapOffset(moduleRow.EncId), metadataSizes.GuidIndexSize); writer.WriteReference((uint)GetHeapOffset(moduleRow.EncBaseId), metadataSizes.GuidIndexSize); } }
private void SerializeImplMapTable(BlobBuilder writer, MetadataSizes metadataSizes) { #if DEBUG for (int i = 1; i < _implMapTable.Count; i++) { Debug.Assert(_implMapTable[i - 1].MemberForwarded < _implMapTable[i].MemberForwarded); } #endif foreach (ImplMapRow implMap in _implMapTable) { writer.WriteUInt16(implMap.MappingFlags); writer.WriteReference(implMap.MemberForwarded, metadataSizes.MemberForwardedCodedIndexSize); writer.WriteReference((uint)GetHeapOffset(implMap.ImportName), metadataSizes.StringIndexSize); writer.WriteReference(implMap.ImportScope, metadataSizes.ModuleRefIndexSize); } }
private void SerializeFieldTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (FieldDefRow fieldDef in _fieldTable) { writer.WriteUInt16(fieldDef.Flags); writer.WriteReference((uint)GetHeapOffset(fieldDef.Name), metadataSizes.StringIndexSize); writer.WriteReference((uint)GetHeapOffset(fieldDef.Signature), metadataSizes.BlobIndexSize); } }
private void SerializeGenericParamTable(BlobBuilder writer, MetadataSizes metadataSizes) { #if DEBUG for (int i = 1; i < _genericParamTable.Count; i++) { Debug.Assert( _genericParamTable[i - 1].Owner < _genericParamTable[i].Owner || _genericParamTable[i - 1].Owner == _genericParamTable[i].Owner && _genericParamTable[i - 1].Number < _genericParamTable[i].Number); } #endif foreach (GenericParamRow genericParam in _genericParamTable) { writer.WriteUInt16(genericParam.Number); writer.WriteUInt16(genericParam.Flags); writer.WriteReference(genericParam.Owner, metadataSizes.TypeOrMethodDefCodedIndexSize); writer.WriteReference((uint)GetHeapOffset(genericParam.Name), metadataSizes.StringIndexSize); } }
private void SerializeMethodDefTable(BlobBuilder writer, MetadataSizes metadataSizes, int methodBodyStreamRva) { foreach (MethodRow method in _methodDefTable) { if (method.BodyOffset == -1) { writer.WriteUInt32(0); } else { writer.WriteUInt32((uint)(methodBodyStreamRva + method.BodyOffset)); } writer.WriteUInt16(method.ImplFlags); writer.WriteUInt16(method.Flags); writer.WriteReference((uint)GetHeapOffset(method.Name), metadataSizes.StringIndexSize); writer.WriteReference((uint)GetHeapOffset(method.Signature), metadataSizes.BlobIndexSize); writer.WriteReference(method.ParamList, metadataSizes.ParameterIndexSize); } }
private static void WriteRelocationSection(BlobBuilder builder, Machine machine, int entryPointAddress) { Debug.Assert(builder.Count == 0); builder.WriteUInt32((((uint)entryPointAddress + 2) / 0x1000) * 0x1000); builder.WriteUInt32((machine == Machine.IA64) ? 14u : 12u); uint offsetWithinPage = ((uint)entryPointAddress + 2) % 0x1000; uint relocType = (machine == Machine.Amd64 || machine == Machine.IA64) ? 10u : 3u; ushort s = (ushort)((relocType << 12) | offsetWithinPage); builder.WriteUInt16(s); if (machine == Machine.IA64) { builder.WriteUInt32(relocType << 12); } builder.WriteUInt16(0); // next chunk's RVA }
private void WriteCoffHeader(BlobBuilder builder, ImmutableArray<SerializedSection> sections, out Blob stampFixup) { // Machine builder.WriteUInt16((ushort)(Header.Machine == 0 ? Machine.I386 : Header.Machine)); // NumberOfSections builder.WriteUInt16((ushort)sections.Length); // TimeDateStamp: stampFixup = builder.ReserveBytes(sizeof(uint)); // PointerToSymbolTable (TODO: not supported): // The file pointer to the COFF symbol table, or zero if no COFF symbol table is present. // This value should be zero for a PE image. builder.WriteUInt32(0); // NumberOfSymbols (TODO: not supported): // The number of entries in the symbol table. This data can be used to locate the string table, // which immediately follows the symbol table. This value should be zero for a PE image. builder.WriteUInt32(0); // SizeOfOptionalHeader: // The size of the optional header, which is required for executable files but not for object files. // This value should be zero for an object file (TODO). builder.WriteUInt16((ushort)(Header.Is32Bit ? 224 : 240)); // Characteristics builder.WriteUInt16((ushort)Header.ImageCharacteristics); }