Exemplo n.º 1
0
        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)PEHeader.Size(Header.Is32Bit));

            // Characteristics
            builder.WriteUInt16((ushort)Header.ImageCharacteristics);
        }
Exemplo n.º 2
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
            }
        }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
        // Adapted from: https://github.com/dotnet/corefx/blob/772a2486f2dd29f3a0401427a26da23e845a6e59/src/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/Encoding/MethodBodyStreamEncoder.cs#L222-L272
        //
        private int SerializeHeader(int codeSize, int maxStack, int exceptionRegionCount,
                                    MethodBodyAttributes attributes, StandaloneSignatureHandle localVariablesSignature,
                                    bool hasDynamicStackAllocation)
        {
            const int  TinyFormat   = 2;
            const int  FatFormat    = 3;
            const int  MoreSections = 8;
            const byte InitLocals   = 0x10;

            var initLocals = (attributes & MethodBodyAttributes.InitLocals) != 0;

            var isTiny = codeSize < 64 &&
                         maxStack <= 8 &&
                         localVariablesSignature.IsNil && (!hasDynamicStackAllocation || !initLocals) &&
                         exceptionRegionCount == 0;

            int offset;

            if (isTiny)
            {
                offset = _builder.Count;
                _builder.WriteByte((byte)((codeSize << 2) | TinyFormat));
            }
            else
            {
                _builder.Align(4);

                offset = _builder.Count;

                ushort flags = (3 << 12) | FatFormat;
                if (exceptionRegionCount > 0)
                {
                    flags |= MoreSections;
                }

                if (initLocals)
                {
                    flags |= InitLocals;
                }

                _builder.WriteUInt16((ushort)((int)attributes | flags));
                _builder.WriteUInt16((ushort)maxStack);
                _builder.WriteInt32(codeSize);
                _builder.WriteInt32(
                    localVariablesSignature.IsNil ? 0 : MetadataTokens.GetToken(localVariablesSignature));
            }

            return(offset);
        }
        internal static ExceptionRegionEncoder SerializeTableHeader(BlobBuilder builder, int exceptionRegionCount, bool hasSmallRegions)
        {
            Debug.Assert(exceptionRegionCount > 0);

            const byte EHTableFlag   = 0x01;
            const byte FatFormatFlag = 0x40;

            bool hasSmallFormat = hasSmallRegions && IsSmallRegionCount(exceptionRegionCount);
            int  dataSize       = GetExceptionTableSize(exceptionRegionCount, hasSmallFormat);

            builder.Align(4);
            if (hasSmallFormat)
            {
                builder.WriteByte(EHTableFlag);
                builder.WriteByte(unchecked ((byte)dataSize));
                builder.WriteInt16(0);
            }
            else
            {
                Debug.Assert(dataSize <= 0x00ffffff);
                builder.WriteByte(EHTableFlag | FatFormatFlag);
                builder.WriteByte(unchecked ((byte)dataSize));
                builder.WriteUInt16(unchecked ((ushort)(dataSize >> 8)));
            }

            return(new ExceptionRegionEncoder(builder, hasSmallFormat));
        }
Exemplo n.º 6
0
        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 || machine == Machine.Arm64) ? 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
        }
Exemplo n.º 7
0
        /// <summary>
        /// Helper method to serialize CorHeader into a BlobBuilder.
        /// </summary>
        /// <param name="builder">Target blob builder to receive the serialized data</param>
        public void WriteTo(BlobBuilder builder)
        {
            builder.WriteInt32(CorHeaderSize);

            builder.WriteUInt16(MajorRuntimeVersion);
            builder.WriteUInt16(MinorRuntimeVersion);

            WriteDirectoryEntry(MetadataDirectory, builder);

            builder.WriteUInt32((uint)Flags);
            builder.WriteInt32(EntryPointTokenOrRelativeVirtualAddress);

            WriteDirectoryEntry(ResourcesDirectory, builder);
            WriteDirectoryEntry(StrongNameSignatureDirectory, builder);
            WriteDirectoryEntry(CodeManagerTableDirectory, builder);
            WriteDirectoryEntry(VtableFixupsDirectory, builder);
            WriteDirectoryEntry(ExportAddressTableJumpsDirectory, builder);
            WriteDirectoryEntry(ManagedNativeHeaderDirectory, builder);
        }
Exemplo n.º 8
0
        public void Serialize(BlobBuilder writer)
        {
            switch (this.Discriminator)
            {
            case ConstantValueTypeDiscriminator.Boolean:
                writer.WriteBoolean(this.BooleanValue);
                break;

            case ConstantValueTypeDiscriminator.SByte:
                writer.WriteSByte(this.SByteValue);
                break;

            case ConstantValueTypeDiscriminator.Byte:
                writer.WriteByte(this.ByteValue);
                break;

            case ConstantValueTypeDiscriminator.Char:
            case ConstantValueTypeDiscriminator.Int16:
                writer.WriteInt16(this.Int16Value);
                break;

            case ConstantValueTypeDiscriminator.UInt16:
                writer.WriteUInt16(this.UInt16Value);
                break;

            case ConstantValueTypeDiscriminator.Single:
                writer.WriteSingle(this.SingleValue);
                break;

            case ConstantValueTypeDiscriminator.Int32:
                writer.WriteInt32(this.Int32Value);
                break;

            case ConstantValueTypeDiscriminator.UInt32:
                writer.WriteUInt32(this.UInt32Value);
                break;

            case ConstantValueTypeDiscriminator.Double:
                writer.WriteDouble(this.DoubleValue);
                break;

            case ConstantValueTypeDiscriminator.Int64:
                writer.WriteInt64(this.Int64Value);
                break;

            case ConstantValueTypeDiscriminator.UInt64:
                writer.WriteUInt64(this.UInt64Value);
                break;

            default:
                throw ExceptionUtilities.UnexpectedValue(this.Discriminator);
            }
        }
Exemplo n.º 9
0
 /// <summary>
 /// Serialize a block of relocations into the .reloc section.
 /// </summary>
 /// <param name="builder">Output blob builder to receive the serialized relocation block</param>
 /// <param name="baseRVA">Base RVA of the relocation block</param>
 /// <param name="offsetsAndTypes">16-bit entries encoding offset relative to the base RVA (low 12 bits) and relocation type (top 4 bite)</param>
 private static void FlushRelocationBlock(BlobBuilder builder, int baseRVA, List <ushort> offsetsAndTypes)
 {
     // First, emit the block header: 4 bytes starting RVA,
     builder.WriteInt32(baseRVA);
     // followed by the total block size comprising this header
     // and following 16-bit entries.
     builder.WriteInt32(4 + 4 + 2 * offsetsAndTypes.Count);
     // Now serialize out the entries
     foreach (ushort offsetAndType in offsetsAndTypes)
     {
         builder.WriteUInt16(offsetAndType);
     }
 }
Exemplo n.º 10
0
        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);
        }
Exemplo n.º 11
0
        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);
        }
        public void WritePrimitive()
        {
            var writer = new BlobBuilder(17);

            writer.WriteUInt32(0x11223344);
            writer.WriteUInt16(0x5566);
            writer.WriteByte(0x77);
            writer.WriteUInt64(0x8899aabbccddeeff);
            writer.WriteInt32(-1);
            writer.WriteInt16(-2);
            writer.WriteSByte(-3);
            writer.WriteBoolean(true);
            writer.WriteBoolean(false);
            writer.WriteInt64(unchecked ((long)0xfedcba0987654321));
            writer.WriteDateTime(new DateTime(0x1112223334445556));
            writer.WriteDecimal(102030405060.70m);
            writer.WriteDouble(double.NaN);
            writer.WriteSingle(float.NegativeInfinity);

            var guid = new Guid("01020304-0506-0708-090A-0B0C0D0E0F10");

            writer.WriteBytes(guid.ToByteArray());
            writer.WriteGuid(guid);

            AssertEx.Equal(new byte[]
            {
                0x44, 0x33, 0x22, 0x11,
                0x66, 0x55,
                0x77,
                0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88,
                0xff, 0xff, 0xff, 0xff,
                0xfe, 0xff,
                0xfd,
                0x01,
                0x00,
                0x21, 0x43, 0x65, 0x87, 0x09, 0xBA, 0xDC, 0xFE,
                0x56, 0x55, 0x44, 0x34, 0x33, 0x22, 0x12, 0x11,
                0x02, 0xD6, 0xE0, 0x9A, 0x94, 0x47, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
                0x00, 0x00, 0x80, 0xFF,
                0x04, 0x03, 0x02, 0x01, 0x06, 0x05, 0x08, 0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
                0x04, 0x03, 0x02, 0x01, 0x06, 0x05, 0x08, 0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10
            }, writer.ToArray());
        }
Exemplo n.º 13
0
        /// <summary>
        /// Serialize a block of relocations into the .reloc section.
        /// </summary>
        /// <param name="builder">Output blob builder to receive the serialized relocation block</param>
        /// <param name="baseRVA">Base RVA of the relocation block</param>
        /// <param name="offsetsAndTypes">16-bit entries encoding offset relative to the base RVA (low 12 bits) and relocation type (top 4 bite)</param>
        private static void FlushRelocationBlock(BlobBuilder builder, int baseRVA, List <ushort> offsetsAndTypes)
        {
            // Ensure blocks are 4-byte aligned. This is required by kernel memory manager
            // on Windows 8.1 and earlier.
            if ((offsetsAndTypes.Count & 1) == 1)
            {
                offsetsAndTypes.Add(0);
            }

            // First, emit the block header: 4 bytes starting RVA,
            builder.WriteInt32(baseRVA);
            // followed by the total block size comprising this header
            // and following 16-bit entries.
            builder.WriteInt32(4 + 4 + 2 * offsetsAndTypes.Count);
            // Now serialize out the entries
            foreach (ushort offsetAndType in offsetsAndTypes)
            {
                builder.WriteUInt16(offsetAndType);
            }
        }
Exemplo n.º 14
0
        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);
        }
Exemplo n.º 15
0
        private void WriteDirectory(Directory directory, BlobBuilder writer, uint offset, uint level, uint sizeOfDirectoryTree, int virtualAddressBase, BlobBuilder dataWriter)
        {
            writer.WriteUInt32(0); // Characteristics
            writer.WriteUInt32(0); // Timestamp
            writer.WriteUInt32(0); // Version
            writer.WriteUInt16(directory.NumberOfNamedEntries);
            writer.WriteUInt16(directory.NumberOfIdEntries);
            uint n = (uint)directory.Entries.Count;
            uint k = offset + 16 + n * 8;
            for (int i = 0; i < n; i++)
            {
                int id;
                string name;
                uint nameOffset = (uint)dataWriter.Position + sizeOfDirectoryTree;
                uint directoryOffset = k;
                Directory subDir = directory.Entries[i] as Directory;
                if (subDir != null)
                {
                    id = subDir.ID;
                    name = subDir.Name;
                    if (level == 0)
                    {
                        k += SizeOfDirectory(subDir);
                    }
                    else
                    {
                        k += 16 + 8 * (uint)subDir.Entries.Count;
                    }
                }
                else
                {
                    //EDMAURER write out an IMAGE_RESOURCE_DATA_ENTRY followed
                    //immediately by the data that it refers to. This results
                    //in a layout different than that produced by pulling the resources
                    //from an OBJ. In that case all of the data bits of a resource are
                    //contiguous in .rsrc$02. After processing these will end up at
                    //the end of .rsrc following all of the directory
                    //info and IMAGE_RESOURCE_DATA_ENTRYs
                    IWin32Resource r = (IWin32Resource)directory.Entries[i];
                    id = level == 0 ? r.TypeId : level == 1 ? r.Id : (int)r.LanguageId;
                    name = level == 0 ? r.TypeName : level == 1 ? r.Name : null;
                    dataWriter.WriteUInt32((uint)(virtualAddressBase + sizeOfDirectoryTree + 16 + dataWriter.Position));
                    byte[] data = new List<byte>(r.Data).ToArray();
                    dataWriter.WriteUInt32((uint)data.Length);
                    dataWriter.WriteUInt32(r.CodePage);
                    dataWriter.WriteUInt32(0);
                    dataWriter.WriteBytes(data);
                    while ((dataWriter.Count % 4) != 0)
                    {
                        dataWriter.WriteByte(0);
                    }
                }

                if (id >= 0)
                {
                    writer.WriteInt32(id);
                }
                else
                {
                    if (name == null)
                    {
                        name = string.Empty;
                    }

                    writer.WriteUInt32(nameOffset | 0x80000000);
                    dataWriter.WriteUInt16((ushort)name.Length);
                    dataWriter.WriteUTF16(name);
                }

                if (subDir != null)
                {
                    writer.WriteUInt32(directoryOffset | 0x80000000);
                }
                else
                {
                    writer.WriteUInt32(nameOffset);
                }
            }

            k = offset + 16 + n * 8;
            for (int i = 0; i < n; i++)
            {
                Directory subDir = directory.Entries[i] as Directory;
                if (subDir != null)
                {
                    this.WriteDirectory(subDir, writer, k, level + 1, sizeOfDirectoryTree, virtualAddressBase, dataWriter);
                    if (level == 0)
                    {
                        k += SizeOfDirectory(subDir);
                    }
                    else
                    {
                        k += 16 + 8 * (uint)subDir.Entries.Count;
                    }
                }
            }
        }
Exemplo n.º 16
0
        private static void WriteNameTable(Stream peStream)
        {
            var writer = new BlobBuilder(SizeOfNameTable);
            foreach (char ch in CorEntryPointDll)
            {
                writer.WriteByte((byte)ch);
            }

            writer.WriteByte(0);
            writer.WriteUInt16(0);
            Debug.Assert(writer.Count == SizeOfNameTable);

            writer.WriteContentTo(peStream);
        }
Exemplo n.º 17
0
        private void WriteRuntimeStartupStub(Stream peStream, int importAddressTableRva)
        {
            var writer = new BlobBuilder(16);
            // entry point code, consisting of a jump indirect to _CorXXXMain
            if (_is32bit)
            {
                //emit 0's (nops) to pad the entry point code so that the target address is aligned on a 4 byte boundary.
                for (uint i = 0, n = (uint)(BitArithmeticUtilities.Align((uint)peStream.Position, 4) - peStream.Position); i < n; i++)
                {
                    writer.WriteByte(0);
                }

                writer.WriteUInt16(0);
                writer.WriteByte(0xff);
                writer.WriteByte(0x25); //4
                writer.WriteUInt32((uint)importAddressTableRva + (uint)_properties.BaseAddress); //8
            }
            else
            {
                //emit 0's (nops) to pad the entry point code so that the target address is aligned on a 8 byte boundary.
                for (uint i = 0, n = (uint)(BitArithmeticUtilities.Align((uint)peStream.Position, 8) - peStream.Position); i < n; i++)
                {
                    writer.WriteByte(0);
                }

                writer.WriteUInt32(0);
                writer.WriteUInt16(0);
                writer.WriteByte(0xff);
                writer.WriteByte(0x25); //8
                writer.WriteUInt64((ulong)importAddressTableRva + _properties.BaseAddress); //16
            }

            writer.WriteContentTo(peStream);
        }
 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 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 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);
            }
        }
Exemplo n.º 21
0
        private static void WriteDirectory(Directory directory, BlobBuilder writer, uint offset, uint level, uint sizeOfDirectoryTree, int virtualAddressBase, BlobBuilder dataWriter)
        {
            writer.WriteUInt32(0); // Characteristics
            writer.WriteUInt32(0); // Timestamp
            writer.WriteUInt32(0); // Version
            writer.WriteUInt16(directory.NumberOfNamedEntries);
            writer.WriteUInt16(directory.NumberOfIdEntries);
            uint n = (uint)directory.Entries.Count;
            uint k = offset + 16 + n * 8;

            for (int i = 0; i < n; i++)
            {
                int       id;
                string    name;
                uint      nameOffset      = (uint)dataWriter.Count + sizeOfDirectoryTree;
                uint      directoryOffset = k;
                Directory subDir          = directory.Entries[i] as Directory;
                if (subDir != null)
                {
                    id   = subDir.ID;
                    name = subDir.Name;
                    if (level == 0)
                    {
                        k += SizeOfDirectory(subDir);
                    }
                    else
                    {
                        k += 16 + 8 * (uint)subDir.Entries.Count;
                    }
                }
                else
                {
                    //EDMAURER write out an IMAGE_RESOURCE_DATA_ENTRY followed
                    //immediately by the data that it refers to. This results
                    //in a layout different than that produced by pulling the resources
                    //from an OBJ. In that case all of the data bits of a resource are
                    //contiguous in .rsrc$02. After processing these will end up at
                    //the end of .rsrc following all of the directory
                    //info and IMAGE_RESOURCE_DATA_ENTRYs
                    IWin32Resource r = (IWin32Resource)directory.Entries[i];
                    id   = level == 0 ? r.TypeId : level == 1 ? r.Id : (int)r.LanguageId;
                    name = level == 0 ? r.TypeName : level == 1 ? r.Name : null;
                    dataWriter.WriteUInt32((uint)(virtualAddressBase + sizeOfDirectoryTree + 16 + dataWriter.Count));
                    byte[] data = new List <byte>(r.Data).ToArray();
                    dataWriter.WriteUInt32((uint)data.Length);
                    dataWriter.WriteUInt32(r.CodePage);
                    dataWriter.WriteUInt32(0);
                    dataWriter.WriteBytes(data);
                    while ((dataWriter.Count % 4) != 0)
                    {
                        dataWriter.WriteByte(0);
                    }
                }

                if (id >= 0)
                {
                    writer.WriteInt32(id);
                }
                else
                {
                    if (name == null)
                    {
                        name = string.Empty;
                    }

                    writer.WriteUInt32(nameOffset | 0x80000000);
                    dataWriter.WriteUInt16((ushort)name.Length);
                    dataWriter.WriteUTF16(name);
                }

                if (subDir != null)
                {
                    writer.WriteUInt32(directoryOffset | 0x80000000);
                }
                else
                {
                    writer.WriteUInt32(nameOffset);
                }
            }

            k = offset + 16 + n * 8;
            for (int i = 0; i < n; i++)
            {
                Directory subDir = directory.Entries[i] as Directory;
                if (subDir != null)
                {
                    WriteDirectory(subDir, writer, k, level + 1, sizeOfDirectoryTree, virtualAddressBase, dataWriter);
                    if (level == 0)
                    {
                        k += SizeOfDirectory(subDir);
                    }
                    else
                    {
                        k += 16 + 8 * (uint)subDir.Entries.Count;
                    }
                }
            }
        }
Exemplo n.º 22
0
        internal static ExceptionRegionEncoder SerializeTableHeader(BlobBuilder builder, int exceptionRegionCount, bool hasSmallRegions)
        {
            Debug.Assert(exceptionRegionCount > 0);

            const byte EHTableFlag = 0x01;
            const byte FatFormatFlag = 0x40;

            bool hasSmallFormat = hasSmallRegions && IsSmallRegionCount(exceptionRegionCount);
            int dataSize = GetExceptionTableSize(exceptionRegionCount, hasSmallFormat);

            builder.Align(4);
            if (hasSmallFormat)
            {
                builder.WriteByte(EHTableFlag);
                builder.WriteByte(unchecked((byte)dataSize));
                builder.WriteInt16(0);
            }
            else
            {
                Debug.Assert(dataSize <= 0x00ffffff);
                builder.WriteByte(EHTableFlag | FatFormatFlag);
                builder.WriteByte(unchecked((byte)dataSize));
                builder.WriteUInt16(unchecked((ushort)(dataSize >> 8)));
            }

            return new ExceptionRegionEncoder(builder, hasSmallFormat);
        }
Exemplo n.º 23
0
        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 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);
     }
 }
Exemplo n.º 25
0
        public void WritePrimitive()
        {
            var writer = new BlobBuilder(17);

            writer.WriteUInt32(0x11223344);
            writer.WriteUInt16(0x5566);
            writer.WriteByte(0x77);
            writer.WriteUInt64(0x8899aabbccddeeff);
            writer.WriteInt32(-1);
            writer.WriteInt16(-2);
            writer.WriteSByte(-3);
            writer.WriteBoolean(true);
            writer.WriteBoolean(false);
            writer.WriteInt64(unchecked((long)0xfedcba0987654321));
            writer.WriteDateTime(new DateTime(0x1112223334445556));
            writer.WriteDecimal(102030405060.70m);
            writer.WriteDouble(double.NaN);
            writer.WriteSingle(float.NegativeInfinity);

            var guid = new Guid("01020304-0506-0708-090A-0B0C0D0E0F10");
            writer.WriteBytes(guid.ToByteArray());
            writer.WriteGuid(guid);

            AssertEx.Equal(new byte[]
            {
                0x44, 0x33, 0x22, 0x11,
                0x66, 0x55,
                0x77,
                0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88,
                0xff, 0xff, 0xff, 0xff,
                0xfe, 0xff,
                0xfd,
                0x01,
                0x00,
                0x21, 0x43, 0x65, 0x87, 0x09, 0xBA, 0xDC, 0xFE,
                0x56, 0x55, 0x44, 0x34, 0x33, 0x22, 0x12, 0x11,
                0x02, 0xD6, 0xE0, 0x9A, 0x94, 0x47, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
                0x00, 0x00, 0x80, 0xFF,
                0x04, 0x03, 0x02, 0x01, 0x06, 0x05, 0x08, 0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
                0x04, 0x03, 0x02, 0x01, 0x06, 0x05, 0x08, 0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10
            }, writer.ToArray());
        }
 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 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 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 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 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);
     }
 }
Exemplo n.º 32
0
        public static void Write(
            BlobBuilder writer,
            IReadOnlyList <Instruction> il,
            Func <string, StringHandle> getString,
            IReadOnlyDictionary <Guid, EntityHandle> typeHandles,
            IReadOnlyDictionary <ConstructorInfo, MemberReferenceHandle> ctorRefHandles,
            IReadOnlyDictionary <FieldInfo, FieldDefinitionHandle> fieldHandles,
            IReadOnlyDictionary <MethodInfo, MethodDefinitionHandle> methodHandles)
        {
            var targetOffsets = new ArrayMapper <int>();

            //var offsetIndex = new Dictionary<int, int>();

            for (var i = 0; i < il.Count; i++)
            {
                //offsetIndex.Add(il[i].Offset, i);

                var opCode = il[i].OpCode;

                opCode.WriteOpCode(writer.WriteByte);

                switch (opCode.OperandType)
                {
                case OperandType.InlineNone:
                    break;

                case OperandType.InlineSwitch:
                    var branches = (int[])il[i].Operand;
                    writer.WriteInt32(branches.Length);
                    for (var k = 0; k < branches.Length; k++)
                    {
                        var branchOffset = branches[k];
                        writer.WriteInt32(targetOffsets.Add(
                                              branchOffset + il[i].Offset + opCode.Size + 4 * (branches.Length + 1)));
                    }

                    break;

                case OperandType.ShortInlineBrTarget:
                    var offset8 = (sbyte)il[i].Operand;
                    // offset convention in IL: zero is at next instruction
                    writer.WriteSByte((sbyte)targetOffsets.Add(offset8 + il[i].Offset + opCode.Size + 1));
                    break;

                case OperandType.InlineBrTarget:
                    var offset32 = (int)il[i].Operand;
                    // offset convention in IL: zero is at next instruction
                    writer.WriteInt32(targetOffsets.Add(offset32 + il[i].Offset + opCode.Size + 4));
                    break;

                case OperandType.ShortInlineI:
                    if (opCode == OpCodes.Ldc_I4_S)
                    {
                        writer.WriteSByte((sbyte)il[i].Operand);
                    }
                    else
                    {
                        writer.WriteByte((byte)il[i].Operand);
                    }

                    break;

                case OperandType.InlineI:
                    writer.WriteInt32((int)il[i].Operand);
                    break;

                case OperandType.ShortInlineR:
                    writer.WriteSingle((float)il[i].Operand);
                    break;

                case OperandType.InlineR:
                    writer.WriteDouble((double)il[i].Operand);
                    break;

                case OperandType.InlineI8:
                    writer.WriteInt64((long)il[i].Operand);
                    break;

                case OperandType.InlineSig:
                    writer.WriteBytes((byte[])il[i].Operand);
                    break;

                case OperandType.InlineString:
                    writer.WriteInt32(MetadataTokens.GetToken(getString((string)il[i].Operand)));
                    break;

                case OperandType.InlineType:
                case OperandType.InlineTok:
                case OperandType.InlineMethod:
                case OperandType.InlineField:
                    switch (il[i].Operand)
                    {
                    case Type type:
                        writer.WriteInt32(MetadataTokens.GetToken(typeHandles[type.GUID]));
                        break;

                    case ConstructorInfo constructorInfo:
                        writer.WriteInt32(MetadataTokens.GetToken(ctorRefHandles[constructorInfo]));
                        break;

                    case FieldInfo fieldInfo:
                        writer.WriteInt32(MetadataTokens.GetToken(fieldHandles[fieldInfo]));
                        break;

                    case MethodInfo methodInfo:
                        writer.WriteInt32(MetadataTokens.GetToken(methodHandles[methodInfo]));
                        break;

                    default:
                        throw new NotSupportedException();
                    }

                    break;

                case OperandType.ShortInlineVar:
                    var bLocalVariableInfo = il[i].Operand as LocalVariableInfo;
                    var bParameterInfo     = il[i].Operand as ParameterInfo;

                    if (bLocalVariableInfo != null)
                    {
                        writer.WriteByte((byte)bLocalVariableInfo.LocalIndex);
                    }
                    else if (bParameterInfo != null)
                    {
                        writer.WriteByte((byte)bParameterInfo.Position);
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }

                    break;

                case OperandType.InlineVar:
                    var sLocalVariableInfo = il[i].Operand as LocalVariableInfo;
                    var sParameterInfo     = il[i].Operand as ParameterInfo;

                    if (sLocalVariableInfo != null)
                    {
                        writer.WriteUInt16((ushort)sLocalVariableInfo.LocalIndex);
                    }
                    else if (sParameterInfo != null)
                    {
                        writer.WriteUInt16((ushort)sParameterInfo.Position);
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }

                    break;

                default:
                    throw new NotSupportedException();
                }
            }
        }
Exemplo n.º 33
0
        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);
        }
 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);
     }
 }
Exemplo n.º 35
0
        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.
            _lazyChecksum = builder.ReserveBytes(sizeof(uint));
            new BlobWriter(_lazyChecksum).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);
        }
Exemplo n.º 36
0
        private static void WriteSectionHeader(SectionHeader sectionHeader, BlobBuilder writer)
        {
            if (sectionHeader.VirtualSize == 0)
            {
                return;
            }

            for (int j = 0, m = sectionHeader.Name.Length; j < 8; j++)
            {
                if (j < m)
                {
                    writer.WriteByte((byte)sectionHeader.Name[j]);
                }
                else
                {
                    writer.WriteByte(0);
                }
            }

            writer.WriteUInt32((uint)sectionHeader.VirtualSize);
            writer.WriteUInt32((uint)sectionHeader.RelativeVirtualAddress);
            writer.WriteUInt32((uint)sectionHeader.SizeOfRawData);
            writer.WriteUInt32((uint)sectionHeader.PointerToRawData);
            writer.WriteUInt32((uint)sectionHeader.PointerToRelocations);
            writer.WriteUInt32((uint)sectionHeader.PointerToLinenumbers);
            writer.WriteUInt16(sectionHeader.NumberOfRelocations);
            writer.WriteUInt16(sectionHeader.NumberOfLinenumbers);
            writer.WriteUInt32((uint)sectionHeader.Characteristics);
        }
Exemplo n.º 37
0
        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 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);
     }
 }
Exemplo n.º 39
0
        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
            {
                // TODO: message
                throw new ArgumentException();
            }
        }
Exemplo n.º 40
0
        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);
        }
Exemplo n.º 41
0
        private static void WriteRelocSection(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
        }
Exemplo n.º 42
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
            }
        }
Exemplo n.º 43
0
        /// <summary>
        /// Serialize the export symbol table into the export section.
        /// </summary>
        /// <param name="location">RVA and file location of the .edata section</param>
        private BlobBuilder SerializeExportSection(SectionLocation sectionLocation)
        {
            _exportSymbols.MergeSort((es1, es2) => StringComparer.Ordinal.Compare(es1.Name, es2.Name));

            BlobBuilder builder = new BlobBuilder();

            int minOrdinal = int.MaxValue;
            int maxOrdinal = int.MinValue;

            // First, emit the name table and store the name RVA's for the individual export symbols
            // Also, record the ordinal range.
            foreach (ExportSymbol symbol in _exportSymbols)
            {
                symbol.NameRVAWhenPlaced = sectionLocation.RelativeVirtualAddress + builder.Count;
                builder.WriteUTF8(symbol.Name);
                builder.WriteByte(0);

                if (symbol.Ordinal < minOrdinal)
                {
                    minOrdinal = symbol.Ordinal;
                }
                if (symbol.Ordinal > maxOrdinal)
                {
                    maxOrdinal = symbol.Ordinal;
                }
            }

            // Emit the DLL name
            int dllNameRVA = sectionLocation.RelativeVirtualAddress + builder.Count;

            builder.WriteUTF8(_dllNameForExportDirectoryTable);
            builder.WriteByte(0);

            int[] addressTable = new int[maxOrdinal - minOrdinal + 1];

            // Emit the name pointer table; it should be alphabetically sorted.
            // Also, we can now fill in the export address table as we've detected its size
            // in the previous pass.
            int namePointerTableRVA = sectionLocation.RelativeVirtualAddress + builder.Count;

            foreach (ExportSymbol symbol in _exportSymbols)
            {
                builder.WriteInt32(symbol.NameRVAWhenPlaced);
                SymbolTarget symbolTarget  = _symbolMap[symbol.Symbol];
                Section      symbolSection = _sections[symbolTarget.SectionIndex];
                Debug.Assert(symbolSection.RVAWhenPlaced != 0);
                addressTable[symbol.Ordinal - minOrdinal] = symbolSection.RVAWhenPlaced + symbolTarget.Offset;
            }

            // Emit the ordinal table
            int ordinalTableRVA = sectionLocation.RelativeVirtualAddress + builder.Count;

            foreach (ExportSymbol symbol in _exportSymbols)
            {
                builder.WriteUInt16((ushort)(symbol.Ordinal - minOrdinal));
            }

            // Emit the address table
            int addressTableRVA = sectionLocation.RelativeVirtualAddress + builder.Count;

            foreach (int addressTableEntry in addressTable)
            {
                builder.WriteInt32(addressTableEntry);
            }

            // Emit the export directory table
            int exportDirectoryTableRVA = sectionLocation.RelativeVirtualAddress + builder.Count;

            // +0x00: reserved
            builder.WriteInt32(0);
            // +0x04: TODO: time/date stamp
            builder.WriteInt32(0);
            // +0x08: major version
            builder.WriteInt16(0);
            // +0x0A: minor version
            builder.WriteInt16(0);
            // +0x0C: DLL name RVA
            builder.WriteInt32(dllNameRVA);
            // +0x10: ordinal base
            builder.WriteInt32(minOrdinal);
            // +0x14: number of entries in the address table
            builder.WriteInt32(addressTable.Length);
            // +0x18: number of name pointers
            builder.WriteInt32(_exportSymbols.Count);
            // +0x1C: export address table RVA
            builder.WriteInt32(addressTableRVA);
            // +0x20: name pointer RVV
            builder.WriteInt32(namePointerTableRVA);
            // +0x24: ordinal table RVA
            builder.WriteInt32(ordinalTableRVA);
            int exportDirectorySize = sectionLocation.RelativeVirtualAddress + builder.Count - exportDirectoryTableRVA;

            _exportDirectoryEntry = new DirectoryEntry(relativeVirtualAddress: exportDirectoryTableRVA, size: exportDirectorySize);

            return(builder);
        }
Exemplo n.º 44
0
        private void SerializeMetadataHeader(BlobBuilder builder)
        {
            int startOffset = builder.Count;

            // signature
            builder.WriteUInt32(0x424A5342);

            // major version
            builder.WriteUInt16(1);

            // minor version
            builder.WriteUInt16(1);

            // reserved
            builder.WriteUInt32(0);

            // metadata version length
            builder.WriteUInt32(MetadataSizes.MetadataVersionPaddedLength);

            int n = Math.Min(MetadataSizes.MetadataVersionPaddedLength, _metadataVersion.Length);

            for (int i = 0; i < n; i++)
            {
                builder.WriteByte((byte)_metadataVersion[i]);
            }

            for (int i = n; i < MetadataSizes.MetadataVersionPaddedLength; i++)
            {
                builder.WriteByte(0);
            }

            // reserved
            builder.WriteUInt16(0);

            // number of streams
            builder.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", builder);
            }

            // 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 ? "#~" : "#-"), builder);

            SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.GetAlignedHeapSize(HeapIndex.String), "#Strings", builder);
            SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.GetAlignedHeapSize(HeapIndex.UserString), "#US", builder);
            SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.GetAlignedHeapSize(HeapIndex.Guid), "#GUID", builder);
            SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.GetAlignedHeapSize(HeapIndex.Blob), "#Blob", builder);

            if (_sizes.IsMinimalDelta)
            {
                SerializeStreamHeader(ref offsetFromStartOfMetadata, 0, "#JTD", builder);
            }

            int endOffset = builder.Count;

            Debug.Assert(endOffset - startOffset == _sizes.MetadataHeaderSize);
        }
Exemplo n.º 45
0
        private void WriteImportTable(Stream peStream, int importTableRva, int importAddressTableRva)
        {
            var writer = new BlobBuilder(SizeOfImportTable);
            int ilRVA = importTableRva + 40;
            int hintRva = ilRVA + (_is32bit ? 12 : 16);
            int nameRva = hintRva + 12 + 2;

            // Import table
            writer.WriteUInt32((uint)ilRVA); // 4
            writer.WriteUInt32(0); // 8
            writer.WriteUInt32(0); // 12
            writer.WriteUInt32((uint)nameRva); // 16
            writer.WriteUInt32((uint)importAddressTableRva); // 20
            writer.WriteBytes(0, 20); // 40

            // Import Lookup table
            if (_is32bit)
            {
                writer.WriteUInt32((uint)hintRva); // 44
                writer.WriteUInt32(0); // 48
                writer.WriteUInt32(0); // 52
            }
            else
            {
                writer.WriteUInt64((uint)hintRva); // 48
                writer.WriteUInt64(0); // 56
            }

            // Hint table
            writer.WriteUInt16(0); // Hint 54|58

            foreach (char ch in CorEntryPointName)
            {
                writer.WriteByte((byte)ch); // 65|69
            }

            writer.WriteByte(0); // 66|70
            Debug.Assert(writer.Count == SizeOfImportTable);

            writer.WriteContentTo(peStream);
        }
Exemplo n.º 46
0
        private void WriteCoffHeader(BlobBuilder builder, ImmutableArray<SerializedSection> sections, out Blob stampFixup)
        {
            // Machine
            builder.WriteUInt16((ushort)(Machine == 0 ? Machine.I386 : 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)(Is32Bit ? 224 : 240));

            // Characteristics
            builder.WriteUInt16((ushort)ImageCharacteristics);
        }
Exemplo n.º 47
0
        private static void WriteCorHeader(Stream peStream, CorHeader corHeader)
        {
            var writer = new BlobBuilder(CorHeaderSize);
            writer.WriteUInt32(CorHeaderSize);
            writer.WriteUInt16(corHeader.MajorRuntimeVersion);
            writer.WriteUInt16(corHeader.MinorRuntimeVersion); 
            writer.WriteUInt32((uint)corHeader.MetadataDirectory.RelativeVirtualAddress); 
            writer.WriteUInt32((uint)corHeader.MetadataDirectory.Size);
            writer.WriteUInt32((uint)corHeader.Flags);
            writer.WriteUInt32((uint)corHeader.EntryPointTokenOrRelativeVirtualAddress);
            writer.WriteUInt32((uint)(corHeader.ResourcesDirectory.Size == 0 ? 0 : corHeader.ResourcesDirectory.RelativeVirtualAddress)); // 28
            writer.WriteUInt32((uint)corHeader.ResourcesDirectory.Size);
            writer.WriteUInt32((uint)(corHeader.StrongNameSignatureDirectory.Size == 0 ? 0 : corHeader.StrongNameSignatureDirectory.RelativeVirtualAddress)); // 36
            writer.WriteUInt32((uint)corHeader.StrongNameSignatureDirectory.Size);
            writer.WriteUInt32((uint)corHeader.CodeManagerTableDirectory.RelativeVirtualAddress); 
            writer.WriteUInt32((uint)corHeader.CodeManagerTableDirectory.Size); 
            writer.WriteUInt32((uint)corHeader.VtableFixupsDirectory.RelativeVirtualAddress); 
            writer.WriteUInt32((uint)corHeader.VtableFixupsDirectory.Size); 
            writer.WriteUInt32((uint)corHeader.ExportAddressTableJumpsDirectory.RelativeVirtualAddress);
            writer.WriteUInt32((uint)corHeader.ExportAddressTableJumpsDirectory.Size);
            writer.WriteUInt64(0);
            Debug.Assert(writer.Count == CorHeaderSize);
            Debug.Assert(writer.Count % 4 == 0);

            writer.WriteContentTo(peStream);
        }
Exemplo n.º 48
0
        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);
        }
Exemplo n.º 49
0
        private void WriteRelocSection(Stream peStream, SectionHeader relocSection, int entryPointAddress)
        {
            peStream.Position = relocSection.PointerToRawData;
            var writer = new BlobBuilder(relocSection.SizeOfRawData);
            writer.WriteUInt32((((uint)entryPointAddress + 2) / 0x1000) * 0x1000);
            writer.WriteUInt32(_properties.Requires64bits && !_properties.RequiresAmdInstructionSet ? 14u : 12u);
            uint offsetWithinPage = ((uint)entryPointAddress + 2) % 0x1000;
            uint relocType = _properties.Requires64bits ? 10u : 3u;
            ushort s = (ushort)((relocType << 12) | offsetWithinPage);
            writer.WriteUInt16(s);
            if (_properties.Requires64bits && !_properties.RequiresAmdInstructionSet)
            {
                writer.WriteUInt32(relocType << 12);
            }

            writer.WriteUInt16(0); // next chunk's RVA
            writer.PadTo(relocSection.SizeOfRawData);
            writer.WriteContentTo(peStream);
        }
Exemplo n.º 50
0
        private static void WriteSectionHeader(BlobBuilder builder, Section section, SerializedSection serializedSection)
        {
            if (serializedSection.VirtualSize == 0)
            {
                return;
            }

            for (int j = 0, m = section.Name.Length; j < 8; j++)
            {
                if (j < m)
                {
                    builder.WriteByte((byte)section.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)section.Characteristics);
        }
Exemplo n.º 51
0
        internal static void SerializeMetadataHeader(BlobBuilder builder, string metadataVersion, MetadataSizes sizes)
        {
            int startOffset = builder.Count;

            // signature
            builder.WriteUInt32(0x424A5342);

            // major version
            builder.WriteUInt16(1);

            // minor version
            builder.WriteUInt16(1);

            // reserved
            builder.WriteUInt32(0);

            // Spec (section 24.2.1 Metadata Root):
            // Length ... Number of bytes allocated to hold version string (including null terminator), call this x.
            //            Call the length of the string (including the terminator) m (we require m <= 255);
            //            the length x is m rounded up to a multiple of four.
            builder.WriteInt32(sizes.MetadataVersionPaddedLength);

            int metadataVersionStart = builder.Count;

            builder.WriteUTF8(metadataVersion);
            builder.WriteByte(0);
            int metadataVersionEnd = builder.Count;

            for (int i = 0; i < sizes.MetadataVersionPaddedLength - (metadataVersionEnd - metadataVersionStart); i++)
            {
                builder.WriteByte(0);
            }

            // reserved
            builder.WriteUInt16(0);

            // number of streams
            builder.WriteUInt16((ushort)(5 + (sizes.IsEncDelta ? 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", builder);
            }

            // 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.IsCompressed ? "#~" : "#-"), builder);

            SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.String), "#Strings", builder);
            SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.UserString), "#US", builder);
            SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.Guid), "#GUID", builder);
            SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.Blob), "#Blob", builder);

            if (sizes.IsEncDelta)
            {
                SerializeStreamHeader(ref offsetFromStartOfMetadata, 0, "#JTD", builder);
            }

            int endOffset = builder.Count;

            Debug.Assert(endOffset - startOffset == sizes.MetadataHeaderSize);
        }
        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);
            }
        }