public void WriteData(BlobBuilder resourceWriter)
        {
            if (_fileReference == null)
            {
                try
                {
                    using (Stream stream = _streamProvider())
                    {
                        if (stream == null)
                        {
                            throw new InvalidOperationException(CodeAnalysisResources.ResourceStreamProviderShouldReturnNonNullStream);
                        }

                        var count = (int)(stream.Length - stream.Position);
                        resourceWriter.WriteInt32(count);

                        int bytesWritten = resourceWriter.TryWriteBytes(stream, count);
                        if (bytesWritten != count)
                        {
                            throw new EndOfStreamException(
                                    string.Format(CultureInfo.CurrentUICulture, CodeAnalysisResources.ResourceStreamEndedUnexpectedly, bytesWritten, count));
                        }
                        resourceWriter.Align(8);
                    }
                }
                catch (Exception e)
                {
                    throw new ResourceException(_name, e);
                }
            }
        }
Beispiel #2
0
        public void WriteData(BlobBuilder resourceWriter)
        {
            if (_fileReference == null)
            {
                try
                {
                    using (Stream stream = _streamProvider())
                    {
                        if (stream == null)
                        {
                            throw new InvalidOperationException(CodeAnalysisResources.ResourceStreamProviderShouldReturnNonNullStream);
                        }

                        var count = (int)(stream.Length - stream.Position);
                        resourceWriter.WriteInt32(count);

                        resourceWriter.Write(stream, count);
                        resourceWriter.Align(8);
                    }
                }
                catch (Exception e)
                {
                    throw new ResourceException(_name, e);
                }
            }
        }
Beispiel #3
0
        public void Ctor()
        {
            var builder = new BlobBuilder();
            Assert.Equal(BlobBuilder.DefaultChunkSize, builder.BufferSize);

            builder = new BlobBuilder(0);
            Assert.Equal(BlobBuilder.MinChunkSize, builder.BufferSize);

            builder = new BlobBuilder(10001);
            Assert.Equal(10001, builder.BufferSize);
        }
Beispiel #4
0
        private void TestContentEquals(byte[] left, byte[] right)
        {
            var builder1 = new BlobBuilder(0);
            builder1.WriteBytes(left);

            var builder2 = new BlobBuilder(0);
            builder2.WriteBytes(right);

            bool expected = ByteSequenceComparer.Equals(left, right);
            Assert.Equal(expected, builder1.ContentEquals(builder2));
        }
Beispiel #5
0
        public void ContentEquals()
        {
            var builder = new BlobBuilder();
            Assert.True(builder.ContentEquals(builder));
            Assert.False(builder.ContentEquals(null));

            TestContentEquals(new byte[] { }, new byte[] { });
            TestContentEquals(new byte[] { 1 }, new byte[] { });
            TestContentEquals(new byte[] { }, new byte[] { 1 });
            TestContentEquals(new byte[] { 1 }, new byte[] { 1 });

            TestContentEquals(
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 });

            TestContentEquals(
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });

            TestContentEquals(
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 });

            TestContentEquals(
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });

            TestContentEquals(
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });

            TestContentEquals(
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 },
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });

            TestContentEquals(
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 });

            TestContentEquals(
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 },
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 });

            TestContentEquals(
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 },
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 });

            TestContentEquals(
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 },
                new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 });
        }
Beispiel #6
0
 internal PdbLogger(bool logging)
 {
     _logging = logging;
     if (logging)
     {
         _logData = BlobBuilder.GetInstance();
         _hashAlgorithm = new SHA1CryptoServiceProvider();
         Debug.Assert(_hashAlgorithm.SupportsTransform);
     }
     else
     {
         _logData = null;
         _hashAlgorithm = null;
     }
 }
Beispiel #7
0
        public BlobBuilder(int size = DefaultChunkSize)
        {
            if (size < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(size));
            }

            // the writer assumes little-endian architecture:
            if (!BitConverter.IsLittleEndian)
            {
                throw new PlatformNotSupportedException();
            }

            _nextOrPrevious = this;
            _buffer = new byte[Math.Max(MinChunkSize, size)];
        }
Beispiel #8
0
        public void CountClear()
        {
            var builder = new BlobBuilder();
            Assert.Equal(0, builder.Count);

            builder.WriteByte(1);
            Assert.Equal(1, builder.Count);

            builder.WriteInt32(4);
            Assert.Equal(5, builder.Count);

            builder.Clear();
            Assert.Equal(0, builder.Count);

            builder.WriteInt64(1);
            Assert.Equal(8, builder.Count);

            AssertEx.Equal(new byte[] { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, builder.ToArray());
        }
Beispiel #9
0
 internal PdbLogger(bool logging)
 {
     _logging = logging;
     if (logging)
     {
         // do not get this from pool
         // we need a fairly large buffer here (where the pool typically contains small ones)
         // and we need just one per compile session
         // pooling will be couter-productive in such scenario
         _logData = new BlobBuilder(bufferFlushLimit);
         _hashAlgorithm = new SHA1CryptoServiceProvider();
         Debug.Assert(_hashAlgorithm.SupportsTransform);
     }
     else
     {
         _logData = null;
         _hashAlgorithm = null;
     }
 }
Beispiel #10
0
        public void WritePrimitive()
        {
            var writer = new BlobBuilder(4);

            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);

            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
            }, writer.ToArray());
        }
Beispiel #11
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);
        }
Beispiel #12
0
        public void WriteSerializedString()
        {
            var writer = new BlobBuilder(4);

            writer.WriteSerializedString("");
            writer.WriteSerializedString("a");
            writer.WriteSerializedString(null);
            writer.WriteSerializedString("");

            writer.WriteSerializedString("\ud800");       // hi surrogate
            writer.WriteSerializedString("\udc00");       // lo surrogate
            writer.WriteSerializedString("\ud800\udc00"); // pair
            writer.WriteSerializedString("\udc00\ud800"); // lo + hi
            writer.WriteSerializedString("\u1234");

            AssertEx.Equal(new byte[]
            {
                0x00,
                0x01, 0x61,
                0xff,
                0x00,
                0x03, 0xED, 0xA0, 0x80,
                0x03, 0xED, 0xB0, 0x80,
                0x04, 0xF0, 0x90, 0x80, 0x80,
                0x06, 0xED, 0xB0, 0x80, 0xED, 0xA0, 0x80,
                0x03, 0xE1, 0x88, 0xB4
            }, writer.ToArray());
        }
Beispiel #13
0
        public void Pooled()
        {
            var builder1 = PooledBlobBuilder.GetInstance();
            var builder2 = PooledBlobBuilder.GetInstance();
            var builder3 = new BlobBuilder();

            builder1.WriteByte(1);
            builder2.WriteByte(2);
            builder3.WriteByte(3);

            // mix pooled with non-pooled
            builder1.LinkPrefix(builder3);

            builder1.Free();
            builder2.Free();
        }
Beispiel #14
0
        public void WriteBytes2()
        {
            var writer = new BlobBuilder(4);

            writer.WriteBytes(0xff, 0);
            writer.WriteBytes(1, 4);
            writer.WriteBytes(0xff, 0);
            writer.WriteBytes(2, 10);
            writer.WriteBytes(0xff, 0);
            writer.WriteBytes(3, 1);

            AssertEx.Equal(new byte[]
            {
                0x01, 0x01, 0x01, 0x01,
                0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
                0x03
            }, writer.ToArray());
        }
Beispiel #15
0
        public void WriteAlignPad()
        {
            var writer = new BlobBuilder(4);

            writer.WriteByte(0x01);
            writer.PadTo(2);
            writer.WriteByte(0x02);
            writer.Align(4);
            writer.Align(4);

            writer.WriteByte(0x03);
            writer.Align(4);

            writer.WriteByte(0x04);
            writer.WriteByte(0x05);
            writer.Align(8);

            writer.WriteByte(0x06);
            writer.Align(2);
            writer.Align(1);

            AssertEx.Equal(new byte[]
            {
                0x01, 0x00, 0x02, 0x00,
                0x03, 0x00, 0x00, 0x00,
                0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x06, 0x00
            }, writer.ToArray());
        }
Beispiel #16
0
        private void WriteDebugTable(Stream peStream, SectionHeader textSection, ContentId nativePdbContentId, ContentId portablePdbContentId, MetadataSizes metadataSizes)
        {
            Debug.Assert(nativePdbContentId.IsDefault ^ portablePdbContentId.IsDefault);

            var writer = new BlobBuilder();

            // characteristics:
            writer.WriteUInt32(0);

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

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

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

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

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

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

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

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

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

            writer.WriteTo(peStream);
            writer.Free();
        }
Beispiel #17
0
        private bool WritePeToStream(MetadataWriter mdWriter, Func<Stream> getPeStream, Func<Stream> getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt)
        {
            // TODO: we can precalculate the exact size of IL stream
            var ilWriter = new BlobBuilder(32 * 1024);
            var metadataWriter = new BlobBuilder(16 * 1024);
            var mappedFieldDataWriter = new BlobBuilder();
            var managedResourceWriter = new BlobBuilder(1024);

            var debugMetadataWriterOpt = (getPortablePdbStreamOpt != null) ? new BlobBuilder(16 * 1024) : null;

            nativePdbWriterOpt?.SetMetadataEmitter(mdWriter);

            // Since we are producing a full assembly, we should not have a module version ID
            // imposed ahead-of time. Instead we will compute a deterministic module version ID
            // based on the contents of the generated stream.
            Debug.Assert(_properties.PersistentIdentifier == default(Guid));

            int sectionCount = 1;
            if (_properties.RequiresStartupStub) sectionCount++; //.reloc
            if (!IteratorHelper.EnumerableIsEmpty(_nativeResourcesOpt) || _nativeResourceSectionOpt != null) sectionCount++; //.rsrc;

            int sizeOfPeHeaders = ComputeSizeOfPeHeaders(sectionCount);
            int textSectionRva = BitArithmeticUtilities.Align(sizeOfPeHeaders, _properties.SectionAlignment);

            int moduleVersionIdOffsetInMetadataStream;
            int methodBodyStreamRva = textSectionRva + OffsetToILStream;

            int entryPointToken;
            MetadataSizes metadataSizes;
            mdWriter.SerializeMetadataAndIL(
                metadataWriter,
                debugMetadataWriterOpt,
                nativePdbWriterOpt,
                ilWriter,
                mappedFieldDataWriter,
                managedResourceWriter,
                methodBodyStreamRva,
                mdSizes => CalculateMappedFieldDataStreamRva(textSectionRva, mdSizes),
                out moduleVersionIdOffsetInMetadataStream,
                out entryPointToken,
                out metadataSizes);

            ContentId nativePdbContentId;
            if (nativePdbWriterOpt != null)
            {
                if (entryPointToken != 0)
                {
                    nativePdbWriterOpt.SetEntryPoint((uint)entryPointToken);
                }

                var assembly = mdWriter.Module.AsAssembly;
                if (assembly != null && assembly.Kind == OutputKind.WindowsRuntimeMetadata)
                {
                    // Dev12: If compiling to winmdobj, we need to add to PDB source spans of
                    //        all types and members for better error reporting by WinMDExp.
                    nativePdbWriterOpt.WriteDefinitionLocations(mdWriter.Module.GetSymbolToLocationMap());
                }
                else
                {
#if DEBUG
                    // validate that all definitions are writable
                    // if same scenario would happen in an winmdobj project
                    nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap());
#endif
                }

                nativePdbContentId = nativePdbWriterOpt.GetContentId();

                // the writer shall not be used after this point for writing:
                nativePdbWriterOpt = null;
            }
            else
            {
                nativePdbContentId = default(ContentId);
            }
            
            // write to Portable PDB stream:
            ContentId portablePdbContentId;
            Stream portablePdbStream = getPortablePdbStreamOpt?.Invoke();
            if (portablePdbStream != null)
            {
                debugMetadataWriterOpt.WriteTo(portablePdbStream);

                if (_deterministic)
                {
                    portablePdbContentId = ContentId.FromHash(CryptographicHashProvider.ComputeSha1(portablePdbStream));
                }
                else
                {
                    portablePdbContentId = new ContentId(Guid.NewGuid().ToByteArray(), BitConverter.GetBytes(_timeStamp));
                }
            }
            else
            {
                portablePdbContentId = default(ContentId);
            }

            // Only the size of the fixed part of the debug table goes here.
            DirectoryEntry debugDirectory = default(DirectoryEntry);
            DirectoryEntry importTable = default(DirectoryEntry);
            DirectoryEntry importAddressTable = default(DirectoryEntry);
            int entryPointAddress = 0;

            if (EmitPdb)
            {
                debugDirectory = new DirectoryEntry(textSectionRva + ComputeOffsetToDebugTable(metadataSizes), ImageDebugDirectoryBaseSize);
            }

            if (_properties.RequiresStartupStub)
            {
                importAddressTable = new DirectoryEntry(textSectionRva, SizeOfImportAddressTable);
                entryPointAddress = CalculateMappedFieldDataStreamRva(textSectionRva, metadataSizes) - (_is32bit ? 6 : 10); // TODO: constants
                importTable = new DirectoryEntry(textSectionRva + ComputeOffsetToImportTable(metadataSizes), (_is32bit ? 66 : 70) + 13); // TODO: constants
            }

            var corHeaderDirectory = new DirectoryEntry(textSectionRva + SizeOfImportAddressTable, size: CorHeaderSize);

            long ntHeaderTimestampPosition;
            long metadataPosition;

            List<SectionHeader> sectionHeaders = CreateSectionHeaders(metadataSizes, sectionCount);

            CoffHeader coffHeader;
            NtHeader ntHeader;
            FillInNtHeader(sectionHeaders, entryPointAddress, corHeaderDirectory, importTable, importAddressTable, debugDirectory, out coffHeader, out ntHeader);

            Stream peStream = getPeStream();
            if (peStream == null)
            {
                return false;
            }

            WriteHeaders(peStream, ntHeader, coffHeader, sectionHeaders, out ntHeaderTimestampPosition);

            WriteTextSection(
                peStream,
                sectionHeaders[0],
                importTable.RelativeVirtualAddress,
                importAddressTable.RelativeVirtualAddress,
                entryPointToken,
                metadataWriter,
                ilWriter,
                mappedFieldDataWriter,
                managedResourceWriter,
                metadataSizes,
                nativePdbContentId,
                portablePdbContentId,
                out metadataPosition);

            var resourceSection = sectionHeaders.FirstOrDefault(s => s.Name == ResourceSectionName);
            if (resourceSection != null)
            {
                WriteResourceSection(peStream, resourceSection);
            }

            var relocSection = sectionHeaders.FirstOrDefault(s => s.Name == RelocationSectionName);
            if (relocSection != null)
            {
                WriteRelocSection(peStream, relocSection, entryPointAddress);
            }

            if (_deterministic)
            {
                var mvidPosition = metadataPosition + moduleVersionIdOffsetInMetadataStream;
                WriteDeterministicGuidAndTimestamps(peStream, mvidPosition, ntHeaderTimestampPosition);
            }

            return true;
        }
Beispiel #18
0
        public static bool WritePeToStream(
            EmitContext context,
            CommonMessageProvider messageProvider,
            Func <Stream> getPeStream,
            Func <Stream> getPortablePdbStreamOpt,
            PdbWriter nativePdbWriterOpt,
            string pdbPathOpt,
            bool allowMissingMethodBodies,
            bool isDeterministic,
            CancellationToken cancellationToken)
        {
            // If PDB writer is given, we have to have PDB path.
            Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null);

            MetadataWriter mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, isDeterministic, getPortablePdbStreamOpt != null, cancellationToken);

            ModulePropertiesForSerialization properties = context.Module.SerializationProperties;

            nativePdbWriterOpt?.SetMetadataEmitter(mdWriter);

            // Since we are producing a full assembly, we should not have a module version ID
            // imposed ahead-of time. Instead we will compute a deterministic module version ID
            // based on the contents of the generated stream.
            Debug.Assert(properties.PersistentIdentifier == default(Guid));

            BlobBuilder ilBuilder = new BlobBuilder(32 * 1024);
            BlobBuilder mappedFieldDataBuilder = new BlobBuilder();
            BlobBuilder managedResourceBuilder = new BlobBuilder(1024);

            mdWriter.BuildMetadataAndIL(
                nativePdbWriterOpt,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                out Blob mvidFixup,
                out Blob mvidStringFixup);

            mdWriter.GetEntryPoints(out MethodDefinitionHandle entryPointHandle, out MethodDefinitionHandle debugEntryPointHandle);

            if (!debugEntryPointHandle.IsNil)
            {
                nativePdbWriterOpt?.SetEntryPoint((uint)MetadataTokens.GetToken(debugEntryPointHandle));
            }

            if (nativePdbWriterOpt != null)
            {
                if (mdWriter.Module.OutputKind == OutputKind.WindowsRuntimeMetadata)
                {
                    // Dev12: If compiling to winmdobj, we need to add to PDB source spans of
                    //        all types and members for better error reporting by WinMDExp.
                    nativePdbWriterOpt.WriteDefinitionLocations(mdWriter.Module.GetSymbolToLocationMap());
                }
                else
                {
#if DEBUG
                    // validate that all definitions are writable
                    // if same scenario would happen in an winmdobj project
                    nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap());
#endif
                }

                // embedded text not currently supported for native PDB and we should have validated that
                Debug.Assert(!mdWriter.Module.DebugDocumentsBuilder.EmbeddedDocuments.Any());
            }

            Stream peStream = getPeStream();
            if (peStream == null)
            {
                return(false);
            }

            BlobContentId pdbContentId = nativePdbWriterOpt?.GetContentId() ?? default(BlobContentId);

            // the writer shall not be used after this point for writing:
            nativePdbWriterOpt = null;

            ushort portablePdbVersion = 0;
            MetadataRootBuilder metadataRootBuilder = mdWriter.GetRootBuilder();

            PEHeaderBuilder peHeaderBuilder = new PEHeaderBuilder(
                machine: properties.Machine,
                sectionAlignment: properties.SectionAlignment,
                fileAlignment: properties.FileAlignment,
                imageBase: properties.BaseAddress,
                majorLinkerVersion: properties.LinkerMajorVersion,
                minorLinkerVersion: properties.LinkerMinorVersion,
                majorOperatingSystemVersion: 4,
                minorOperatingSystemVersion: 0,
                majorImageVersion: 0,
                minorImageVersion: 0,
                majorSubsystemVersion: properties.MajorSubsystemVersion,
                minorSubsystemVersion: properties.MinorSubsystemVersion,
                subsystem: properties.Subsystem,
                dllCharacteristics: properties.DllCharacteristics,
                imageCharacteristics: properties.ImageCharacteristics,
                sizeOfStackReserve: properties.SizeOfStackReserve,
                sizeOfStackCommit: properties.SizeOfStackCommit,
                sizeOfHeapReserve: properties.SizeOfHeapReserve,
                sizeOfHeapCommit: properties.SizeOfHeapCommit);

            Func <IEnumerable <Blob>, BlobContentId> deterministicIdProvider = isDeterministic ?
                                                                               new Func <IEnumerable <Blob>, BlobContentId>(content => BlobContentId.FromHash(CryptographicHashProvider.ComputeSha1(content))) :
                                                                               null;

            BlobBuilder portablePdbToEmbed = null;
            if (mdWriter.EmitStandaloneDebugMetadata)
            {
                mdWriter.AddRemainingEmbeddedDocuments(mdWriter.Module.DebugDocumentsBuilder.EmbeddedDocuments);

                BlobBuilder        portablePdbBlob    = new BlobBuilder();
                PortablePdbBuilder portablePdbBuilder = mdWriter.GetPortablePdbBuilder(metadataRootBuilder.Sizes.RowCounts, debugEntryPointHandle, deterministicIdProvider);
                pdbContentId       = portablePdbBuilder.Serialize(portablePdbBlob);
                portablePdbVersion = portablePdbBuilder.FormatVersion;

                if (getPortablePdbStreamOpt == null)
                {
                    // embed to debug directory:
                    portablePdbToEmbed = portablePdbBlob;
                }
                else
                {
                    // write to Portable PDB stream:
                    Stream portablePdbStream = getPortablePdbStreamOpt();
                    if (portablePdbStream != null)
                    {
                        portablePdbBlob.WriteContentTo(portablePdbStream);
                    }
                }
            }

            DebugDirectoryBuilder debugDirectoryBuilder;
            if (pdbPathOpt != null || isDeterministic || portablePdbToEmbed != null)
            {
                debugDirectoryBuilder = new DebugDirectoryBuilder();
                if (pdbPathOpt != null)
                {
                    string paddedPath = isDeterministic ? pdbPathOpt : PadPdbPath(pdbPathOpt);
                    debugDirectoryBuilder.AddCodeViewEntry(paddedPath, pdbContentId, portablePdbVersion);
                }

                if (isDeterministic)
                {
                    debugDirectoryBuilder.AddReproducibleEntry();
                }

                if (portablePdbToEmbed != null)
                {
                    debugDirectoryBuilder.AddEmbeddedPortablePdbEntry(portablePdbToEmbed, portablePdbVersion);
                }
            }
            else
            {
                debugDirectoryBuilder = null;
            }

            ManagedPEBuilder peBuilder = new ManagedPEBuilder(
                peHeaderBuilder,
                metadataRootBuilder,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                CreateNativeResourceSectionSerializer(context.Module),
                debugDirectoryBuilder,
                CalculateStrongNameSignatureSize(context.Module),
                entryPointHandle,
                properties.CorFlags,
                deterministicIdProvider);

            BlobBuilder   peBlob      = new BlobBuilder();
            BlobContentId peContentId = peBuilder.Serialize(peBlob);

            PatchModuleVersionIds(mvidFixup, mvidStringFixup, peContentId.Guid);

            try
            {
                peBlob.WriteContentTo(peStream);
            }
            catch (Exception e) when(!(e is OperationCanceledException))
            {
                throw new PeWritingException(e);
            }

            return(true);
        }
Beispiel #19
0
 protected override void Serialize(BlobBuilder builder, SectionLocation location)
 {
     NativeResourceWriter.SerializeWin32Resources(builder, _resources, location.RelativeVirtualAddress);
 }
        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;
                    }
                }
            }
        }
Beispiel #21
0
        internal static bool WritePeToStream(
            EmitContext context,
            CommonMessageProvider messageProvider,
            Func <Stream> getPeStream,
            Func <Stream> getPortablePdbStreamOpt,
            PdbWriter nativePdbWriterOpt,
            string pdbPathOpt,
            bool metadataOnly,
            bool isDeterministic,
            bool emitTestCoverageData,
            RSAParameters?privateKeyOpt,
            CancellationToken cancellationToken)
        {
            // If PDB writer is given, we have to have PDB path.
            Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null);

            var mdWriter = FullMetadataWriter.Create(context, messageProvider, metadataOnly, isDeterministic,
                                                     emitTestCoverageData, getPortablePdbStreamOpt != null, cancellationToken);

            var properties = context.Module.SerializationProperties;

            nativePdbWriterOpt?.SetMetadataEmitter(mdWriter);

            // Since we are producing a full assembly, we should not have a module version ID
            // imposed ahead-of time. Instead we will compute a deterministic module version ID
            // based on the contents of the generated stream.
            Debug.Assert(properties.PersistentIdentifier == default(Guid));

            var ilBuilder = new BlobBuilder(32 * 1024);
            var mappedFieldDataBuilder = new BlobBuilder();
            var managedResourceBuilder = new BlobBuilder(1024);

            Blob mvidFixup, mvidStringFixup;

            mdWriter.BuildMetadataAndIL(
                nativePdbWriterOpt,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                out mvidFixup,
                out mvidStringFixup);

            MethodDefinitionHandle entryPointHandle;
            MethodDefinitionHandle debugEntryPointHandle;

            mdWriter.GetEntryPoints(out entryPointHandle, out debugEntryPointHandle);

            if (!debugEntryPointHandle.IsNil)
            {
                nativePdbWriterOpt?.SetEntryPoint(MetadataTokens.GetToken(debugEntryPointHandle));
            }

            if (nativePdbWriterOpt != null)
            {
                if (context.Module.SourceLinkStreamOpt != null)
                {
                    nativePdbWriterOpt.EmbedSourceLink(context.Module.SourceLinkStreamOpt);
                }

                if (mdWriter.Module.OutputKind == OutputKind.WindowsRuntimeMetadata)
                {
                    // Dev12: If compiling to winmdobj, we need to add to PDB source spans of
                    //        all types and members for better error reporting by WinMDExp.
                    nativePdbWriterOpt.WriteDefinitionLocations(mdWriter.Module.GetSymbolToLocationMap());
                }
                else
                {
#if DEBUG
                    // validate that all definitions are writable
                    // if same scenario would happen in a winmdobj project
                    nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap());
#endif
                }

                nativePdbWriterOpt.WriteRemainingDebugDocuments(mdWriter.Module.DebugDocumentsBuilder.DebugDocuments);
            }

            Stream peStream = getPeStream();
            if (peStream == null)
            {
                return(false);
            }

            BlobContentId pdbContentId = nativePdbWriterOpt?.GetContentId() ?? default;

            // the writer shall not be used after this point for writing:
            nativePdbWriterOpt = null;

            ushort portablePdbVersion  = 0;
            var    metadataRootBuilder = mdWriter.GetRootBuilder();

            var peHeaderBuilder = new PEHeaderBuilder(
                machine: properties.Machine,
                sectionAlignment: properties.SectionAlignment,
                fileAlignment: properties.FileAlignment,
                imageBase: properties.BaseAddress,
                majorLinkerVersion: properties.LinkerMajorVersion,
                minorLinkerVersion: properties.LinkerMinorVersion,
                majorOperatingSystemVersion: 4,
                minorOperatingSystemVersion: 0,
                majorImageVersion: 0,
                minorImageVersion: 0,
                majorSubsystemVersion: properties.MajorSubsystemVersion,
                minorSubsystemVersion: properties.MinorSubsystemVersion,
                subsystem: properties.Subsystem,
                dllCharacteristics: properties.DllCharacteristics,
                imageCharacteristics: properties.ImageCharacteristics,
                sizeOfStackReserve: properties.SizeOfStackReserve,
                sizeOfStackCommit: properties.SizeOfStackCommit,
                sizeOfHeapReserve: properties.SizeOfHeapReserve,
                sizeOfHeapCommit: properties.SizeOfHeapCommit);

            var peIdProvider = isDeterministic ?
                               new Func <IEnumerable <Blob>, BlobContentId>(content => BlobContentId.FromHash(CryptographicHashProvider.ComputeSourceHash(content))) :
                               null;

            // We need to calculate the PDB checksum, so we may as well use the calculated hash for PDB ID regardless of whether deterministic build is requested.
            var portablePdbContentHash = default(ImmutableArray <byte>);

            BlobBuilder portablePdbToEmbed = null;
            if (mdWriter.EmitPortableDebugMetadata)
            {
                mdWriter.AddRemainingDebugDocuments(mdWriter.Module.DebugDocumentsBuilder.DebugDocuments);

                // The algorithm must be specified for deterministic builds (checked earlier).
                Debug.Assert(!isDeterministic || context.Module.PdbChecksumAlgorithm.Name != null);

                var portablePdbIdProvider = (context.Module.PdbChecksumAlgorithm.Name != null) ?
                                            new Func <IEnumerable <Blob>, BlobContentId>(content => BlobContentId.FromHash(portablePdbContentHash = CryptographicHashProvider.ComputeHash(context.Module.PdbChecksumAlgorithm, content))) :
                                            null;

                var portablePdbBlob    = new BlobBuilder();
                var portablePdbBuilder = mdWriter.GetPortablePdbBuilder(metadataRootBuilder.Sizes.RowCounts, debugEntryPointHandle, portablePdbIdProvider);
                pdbContentId       = portablePdbBuilder.Serialize(portablePdbBlob);
                portablePdbVersion = portablePdbBuilder.FormatVersion;

                if (getPortablePdbStreamOpt == null)
                {
                    // embed to debug directory:
                    portablePdbToEmbed = portablePdbBlob;
                }
                else
                {
                    // write to Portable PDB stream:
                    Stream portablePdbStream = getPortablePdbStreamOpt();
                    if (portablePdbStream != null)
                    {
                        try
                        {
                            portablePdbBlob.WriteContentTo(portablePdbStream);
                        }
                        catch (Exception e) when(!(e is OperationCanceledException))
                        {
                            throw new SymUnmanagedWriterException(e.Message, e);
                        }
                    }
                }
            }

            DebugDirectoryBuilder debugDirectoryBuilder;
            if (pdbPathOpt != null || isDeterministic || portablePdbToEmbed != null)
            {
                debugDirectoryBuilder = new DebugDirectoryBuilder();
                if (pdbPathOpt != null)
                {
                    string paddedPath = isDeterministic ? pdbPathOpt : PadPdbPath(pdbPathOpt);
                    debugDirectoryBuilder.AddCodeViewEntry(paddedPath, pdbContentId, portablePdbVersion);

                    if (!portablePdbContentHash.IsDefault)
                    {
                        // Emit PDB Checksum entry for Portable and Embedded PDBs. The checksum is not as useful when the PDB is embedded,
                        // however it allows the client to efficiently validate a standalone Portable PDB that
                        // has been extracted from Embedded PDB and placed next to the PE file.
                        debugDirectoryBuilder.AddPdbChecksumEntry(context.Module.PdbChecksumAlgorithm.Name, portablePdbContentHash);
                    }
                }

                if (isDeterministic)
                {
                    debugDirectoryBuilder.AddReproducibleEntry();
                }

                if (portablePdbToEmbed != null)
                {
                    debugDirectoryBuilder.AddEmbeddedPortablePdbEntry(portablePdbToEmbed, portablePdbVersion);
                }
            }
            else
            {
                debugDirectoryBuilder = null;
            }

            var strongNameProvider = context.Module.CommonCompilation.Options.StrongNameProvider;
            var corFlags           = properties.CorFlags;

            var peBuilder = new ExtendedPEBuilder(
                peHeaderBuilder,
                metadataRootBuilder,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                CreateNativeResourceSectionSerializer(context.Module),
                debugDirectoryBuilder,
                CalculateStrongNameSignatureSize(context.Module, privateKeyOpt),
                entryPointHandle,
                corFlags,
                peIdProvider,
                metadataOnly && !context.IncludePrivateMembers);

            var peBlob      = new BlobBuilder();
            var peContentId = peBuilder.Serialize(peBlob, out Blob mvidSectionFixup);

            PatchModuleVersionIds(mvidFixup, mvidSectionFixup, mvidStringFixup, peContentId.Guid);

            if (privateKeyOpt != null && corFlags.HasFlag(CorFlags.StrongNameSigned))
            {
                strongNameProvider.SignBuilder(peBuilder, peBlob, privateKeyOpt.Value);
            }

            try
            {
                peBlob.WriteContentTo(peStream);
            }
            catch (Exception e) when(!(e is OperationCanceledException))
            {
                throw new PeWritingException(e);
            }

            return(true);
        }
        public static void SerializeWin32Resources(BlobBuilder builder, IEnumerable <IWin32Resource> theResources, int resourcesRva)
        {
            theResources = SortResources(theResources);

            Directory typeDirectory       = new Directory(string.Empty, 0);
            Directory nameDirectory       = null;
            Directory languageDirectory   = null;
            int       lastTypeID          = int.MinValue;
            string    lastTypeName        = null;
            int       lastID              = int.MinValue;
            string    lastName            = null;
            uint      sizeOfDirectoryTree = 16;

            //EDMAURER note that this list is assumed to be sorted lowest to highest
            //first by typeId, then by Id.
            foreach (IWin32Resource r in theResources)
            {
                bool typeDifferent = (r.TypeId < 0 && r.TypeName != lastTypeName) || r.TypeId > lastTypeID;
                if (typeDifferent)
                {
                    lastTypeID   = r.TypeId;
                    lastTypeName = r.TypeName;
                    if (lastTypeID < 0)
                    {
                        Debug.Assert(typeDirectory.NumberOfIdEntries == 0, "Not all Win32 resources with types encoded as strings precede those encoded as ints");
                        typeDirectory.NumberOfNamedEntries++;
                    }
                    else
                    {
                        typeDirectory.NumberOfIdEntries++;
                    }

                    sizeOfDirectoryTree += 24;
                    typeDirectory.Entries.Add(nameDirectory = new Directory(lastTypeName, lastTypeID));
                }

                if (typeDifferent || (r.Id < 0 && r.Name != lastName) || r.Id > lastID)
                {
                    lastID   = r.Id;
                    lastName = r.Name;
                    if (lastID < 0)
                    {
                        Debug.Assert(nameDirectory.NumberOfIdEntries == 0, "Not all Win32 resources with names encoded as strings precede those encoded as ints");
                        nameDirectory.NumberOfNamedEntries++;
                    }
                    else
                    {
                        nameDirectory.NumberOfIdEntries++;
                    }

                    sizeOfDirectoryTree += 24;
                    nameDirectory.Entries.Add(languageDirectory = new Directory(lastName, lastID));
                }

                languageDirectory.NumberOfIdEntries++;
                sizeOfDirectoryTree += 8;
                languageDirectory.Entries.Add(r);
            }

            var dataWriter = new BlobBuilder();

            //'dataWriter' is where opaque resource data goes as well as strings that are used as type or name identifiers
            WriteDirectory(typeDirectory, builder, 0, 0, sizeOfDirectoryTree, resourcesRva, dataWriter);
            builder.LinkSuffix(dataWriter);
            builder.WriteByte(0);
            builder.Align(4);
        }
        private BlobHandle SerializeSequencePoints(
            StandaloneSignatureHandle localSignatureHandleOpt,
            ImmutableArray <SequencePoint> sequencePoints,
            Dictionary <DebugSourceDocument, DocumentHandle> documentIndex,
            out DocumentHandle singleDocumentHandle
            )
        {
            if (sequencePoints.Length == 0)
            {
                singleDocumentHandle = default(DocumentHandle);
                return(default(BlobHandle));
            }

            var writer = new BlobBuilder();

            int previousNonHiddenStartLine   = -1;
            int previousNonHiddenStartColumn = -1;

            // header:
            writer.WriteCompressedInteger(MetadataTokens.GetRowNumber(localSignatureHandleOpt));

            var previousDocument = TryGetSingleDocument(sequencePoints);

            singleDocumentHandle =
                (previousDocument != null)
                    ? GetOrAddDocument(previousDocument, documentIndex)
                    : default(DocumentHandle);

            for (int i = 0; i < sequencePoints.Length; i++)
            {
                var currentDocument = sequencePoints[i].Document;
                if (previousDocument != currentDocument)
                {
                    var documentHandle = GetOrAddDocument(currentDocument, documentIndex);

                    // optional document in header or document record:
                    if (previousDocument != null)
                    {
                        writer.WriteCompressedInteger(0);
                    }

                    writer.WriteCompressedInteger(MetadataTokens.GetRowNumber(documentHandle));
                    previousDocument = currentDocument;
                }

                // delta IL offset:
                if (i > 0)
                {
                    writer.WriteCompressedInteger(
                        sequencePoints[i].Offset - sequencePoints[i - 1].Offset
                        );
                }
                else
                {
                    writer.WriteCompressedInteger(sequencePoints[i].Offset);
                }

                if (sequencePoints[i].IsHidden)
                {
                    writer.WriteInt16(0);
                    continue;
                }

                // Delta Lines & Columns:
                SerializeDeltaLinesAndColumns(writer, sequencePoints[i]);

                // delta Start Lines & Columns:
                if (previousNonHiddenStartLine < 0)
                {
                    Debug.Assert(previousNonHiddenStartColumn < 0);
                    writer.WriteCompressedInteger(sequencePoints[i].StartLine);
                    writer.WriteCompressedInteger(sequencePoints[i].StartColumn);
                }
                else
                {
                    writer.WriteCompressedSignedInteger(
                        sequencePoints[i].StartLine - previousNonHiddenStartLine
                        );
                    writer.WriteCompressedSignedInteger(
                        sequencePoints[i].StartColumn - previousNonHiddenStartColumn
                        );
                }

                previousNonHiddenStartLine   = sequencePoints[i].StartLine;
                previousNonHiddenStartColumn = sequencePoints[i].StartColumn;
            }

            return(_debugMetadataOpt.GetOrAddBlob(writer));
        }
 private static void WriteUtf8String(BlobBuilder builder, string str)
 {
     builder.WriteUTF8(str);
     builder.WriteByte(0);
 }
Beispiel #25
0
        private void WriteImportAddressTable(Stream peStream, int importTableRva)
        {
            var writer = new BlobBuilder(SizeOfImportAddressTable);
            int ilRVA = importTableRva + 40;
            int hintRva = ilRVA + (_is32bit ? 12 : 16);

            // Import Address Table
            if (_is32bit)
            {
                writer.WriteUInt32((uint)hintRva); // 4
                writer.WriteUInt32(0); // 8
            }
            else
            {
                writer.WriteUInt64((uint)hintRva); // 8
                writer.WriteUInt64(0); // 16
            }

            Debug.Assert(writer.Length == SizeOfImportAddressTable);
            writer.WriteTo(peStream);
        }
Beispiel #26
0
 // internal for testing
 internal void ClearChunk()
 {
     _length         = 0;
     _previousLength = 0;
     _nextOrPrevious = this;
 }
Beispiel #27
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.Length == SizeOfNameTable);

            writer.WriteTo(peStream);
        }
Beispiel #28
0
        /// <summary>
        /// Compares the current content of this writer with another one.
        /// </summary>
        /// <exception cref="InvalidOperationException">Content is not available, the builder has been linked with another one.</exception>
        public bool ContentEquals(BlobBuilder other)
        {
            if (!IsHead)
            {
                ThrowHeadRequired();
            }

            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            if (other == null)
            {
                return(false);
            }

            if (!other.IsHead)
            {
                ThrowHeadRequired();
            }

            if (Count != other.Count)
            {
                return(false);
            }

            var leftEnumerator  = GetChunks();
            var rightEnumerator = other.GetChunks();
            int leftStart       = 0;
            int rightStart      = 0;

            bool leftContinues  = leftEnumerator.MoveNext();
            bool rightContinues = rightEnumerator.MoveNext();

            while (leftContinues && rightContinues)
            {
                Debug.Assert(leftStart == 0 || rightStart == 0);

                var left  = leftEnumerator.Current;
                var right = rightEnumerator.Current;

                int minLength = Math.Min(left.Length - leftStart, right.Length - rightStart);
                if (!ByteSequenceComparer.Equals(left._buffer, leftStart, right._buffer, rightStart, minLength))
                {
                    return(false);
                }

                leftStart  += minLength;
                rightStart += minLength;

                // nothing remains in left chunk to compare:
                if (leftStart == left.Length)
                {
                    leftContinues = leftEnumerator.MoveNext();
                    leftStart     = 0;
                }

                // nothing remains in left chunk to compare:
                if (rightStart == right.Length)
                {
                    rightContinues = rightEnumerator.MoveNext();
                    rightStart     = 0;
                }
            }

            return(leftContinues == rightContinues);
        }
Beispiel #29
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.WriteTo(peStream);
        }
Beispiel #30
0
        /// <exception cref="ArgumentNullException"><paramref name="suffix"/> is null.</exception>
        /// <exception cref="InvalidOperationException">Builder is not writable, it has been linked with another one.</exception>
        public void LinkSuffix(BlobBuilder suffix)
        {
            if (suffix == null)
            {
                throw new ArgumentNullException(nameof(suffix));
            }

            // TODO: consider copying data from right to left while there is space

            if (!IsHead || !suffix.IsHead)
            {
                ThrowHeadRequired();
            }

            // avoid chaining empty chunks:
            if (suffix.Count == 0)
            {
                return;
            }

            // swap buffers of the heads:
            var  suffixBuffer = suffix._buffer;
            uint suffixLength = suffix._length;

            suffix._buffer = _buffer;
            suffix._length = FrozenLength; // suffix is not a head anymore
            _buffer        = suffixBuffer;
            _length        = suffixLength;

            int suffixPreviousLength = suffix._previousLength;

            suffix._previousLength = _previousLength;
            _previousLength        = _previousLength + suffix.Length + suffixPreviousLength;

            // First and last chunks:
            //
            // [First]->[]->[Last] <- [this]    [SuffixFirst]->[]->[SuffixLast]  <- [suffix]
            //    ^___________|                       ^_________________|
            //
            // Degenerate cases:
            // this == First == Last and/or suffix == SuffixFirst == SuffixLast.
            var first       = FirstChunk;
            var suffixFirst = suffix.FirstChunk;
            var last        = _nextOrPrevious;
            var suffixLast  = suffix._nextOrPrevious;

            // Relink like so:
            // [First]->[]->[Last] -> [suffix] -> [SuffixFirst]->[]->[SuffixLast]  <- [this]
            //    ^_______________________________________________________|
            _nextOrPrevious        = suffixLast;
            suffix._nextOrPrevious = (suffixFirst != suffix) ? suffixFirst : (first != this) ? first : suffix;

            if (last != this)
            {
                last._nextOrPrevious = suffix;
            }

            if (suffixLast != suffix)
            {
                suffixLast._nextOrPrevious = (first != this) ? first : suffix;
            }

            CheckInvariants();
            suffix.CheckInvariants();
        }
        private void SerializeImport(BlobBuilder writer, UsedNamespaceOrType import)
        {
            if (import.TargetXmlNamespaceOpt != null)
            {
                Debug.Assert(import.TargetNamespaceOpt == null);
                Debug.Assert(import.TargetAssemblyOpt == null);
                Debug.Assert(import.TargetTypeOpt == null);

                // <import> ::= ImportXmlNamespace <alias> <target-namespace>
                writer.WriteByte((byte)ImportDefinitionKind.ImportXmlNamespace);
                writer.WriteCompressedInteger(
                    MetadataTokens.GetHeapOffset(
                        _debugMetadataOpt.GetOrAddBlobUTF8(import.AliasOpt)
                        )
                    );
                writer.WriteCompressedInteger(
                    MetadataTokens.GetHeapOffset(
                        _debugMetadataOpt.GetOrAddBlobUTF8(import.TargetXmlNamespaceOpt)
                        )
                    );
            }
            else if (import.TargetTypeOpt != null)
            {
                Debug.Assert(import.TargetNamespaceOpt == null);
                Debug.Assert(import.TargetAssemblyOpt == null);

                if (import.AliasOpt != null)
                {
                    // <import> ::= AliasType <alias> <target-type>
                    writer.WriteByte((byte)ImportDefinitionKind.AliasType);
                    writer.WriteCompressedInteger(
                        MetadataTokens.GetHeapOffset(
                            _debugMetadataOpt.GetOrAddBlobUTF8(import.AliasOpt)
                            )
                        );
                }
                else
                {
                    // <import> ::= ImportType <target-type>
                    writer.WriteByte((byte)ImportDefinitionKind.ImportType);
                }

                writer.WriteCompressedInteger(
                    CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(import.TargetTypeOpt))
                    ); // TODO: index in release build
            }
            else if (import.TargetNamespaceOpt != null)
            {
                if (import.TargetAssemblyOpt != null)
                {
                    if (import.AliasOpt != null)
                    {
                        // <import> ::= AliasAssemblyNamespace <alias> <target-assembly> <target-namespace>
                        writer.WriteByte((byte)ImportDefinitionKind.AliasAssemblyNamespace);
                        writer.WriteCompressedInteger(
                            MetadataTokens.GetHeapOffset(
                                _debugMetadataOpt.GetOrAddBlobUTF8(import.AliasOpt)
                                )
                            );
                    }
                    else
                    {
                        // <import> ::= ImportAssemblyNamespace <target-assembly> <target-namespace>
                        writer.WriteByte((byte)ImportDefinitionKind.ImportAssemblyNamespace);
                    }

                    writer.WriteCompressedInteger(
                        MetadataTokens.GetRowNumber(
                            GetAssemblyReferenceHandle(import.TargetAssemblyOpt)
                            )
                        );
                }
                else
                {
                    if (import.AliasOpt != null)
                    {
                        // <import> ::= AliasNamespace <alias> <target-namespace>
                        writer.WriteByte((byte)ImportDefinitionKind.AliasNamespace);
                        writer.WriteCompressedInteger(
                            MetadataTokens.GetHeapOffset(
                                _debugMetadataOpt.GetOrAddBlobUTF8(import.AliasOpt)
                                )
                            );
                    }
                    else
                    {
                        // <import> ::= ImportNamespace <target-namespace>
                        writer.WriteByte((byte)ImportDefinitionKind.ImportNamespace);
                    }
                }

                // TODO: cache?
                string namespaceName = TypeNameSerializer.BuildQualifiedNamespaceName(
                    import.TargetNamespaceOpt
                    );
                writer.WriteCompressedInteger(
                    MetadataTokens.GetHeapOffset(_debugMetadataOpt.GetOrAddBlobUTF8(namespaceName))
                    );
            }
            else
            {
                // <import> ::= ImportReferenceAlias <alias>
                Debug.Assert(import.AliasOpt != null);
                Debug.Assert(import.TargetAssemblyOpt == null);

                writer.WriteByte((byte)ImportDefinitionKind.ImportAssemblyReferenceAlias);
                writer.WriteCompressedInteger(
                    MetadataTokens.GetHeapOffset(
                        _debugMetadataOpt.GetOrAddBlobUTF8(import.AliasOpt)
                        )
                    );
            }
        }
Beispiel #32
0
        /// <summary>
        /// Writes information about metadata references to the pdb so the same
        /// reference can be found on sourcelink to create the compilation again
        /// </summary>
        private void EmbedMetadataReferenceInformation(CommonPEModuleBuilder module)
        {
            var builder = new BlobBuilder();

            // Order of information
            // File name (null terminated string): A.exe
            // Extern Alias (null terminated string): a1,a2,a3
            // MetadataImageKind (byte)
            // EmbedInteropTypes (boolean)
            // COFF header Timestamp field (4 byte int)
            // COFF header SizeOfImage field (4 byte int)
            // MVID (Guid, 24 bytes)
            foreach (var metadataReference in module.CommonCompilation.ExternalReferences)
            {
                if (metadataReference is PortableExecutableReference portableReference && portableReference.FilePath is object)
                {
                    var fileName  = PathUtilities.GetFileName(portableReference.FilePath);
                    var reference = module.CommonCompilation.GetAssemblyOrModuleSymbol(portableReference);
                    var peReader  = GetReader(reference);

                    // Don't write before checking that we can get a peReader for the metadata reference
                    if (peReader is null)
                    {
                        continue;
                    }

                    // Write file name first
                    builder.WriteUTF8(fileName);

                    // Make sure to add null terminator
                    builder.WriteByte(0);

                    // Extern alias
                    if (portableReference.Properties.Aliases.Any())
                    {
                        builder.WriteUTF8(string.Join(",", portableReference.Properties.Aliases));
                    }

                    // Always null terminate the extern alias list
                    builder.WriteByte(0);

                    byte kindAndEmbedInteropTypes = (byte)(portableReference.Properties.EmbedInteropTypes
                        ? 0b10
                        : 0b0);

                    kindAndEmbedInteropTypes |= portableReference.Properties.Kind switch
                    {
                        MetadataImageKind.Assembly => 1,
                        MetadataImageKind.Module => 0,
                        _ => throw ExceptionUtilities.UnexpectedValue(portableReference.Properties.Kind)
                    };

                    builder.WriteByte(kindAndEmbedInteropTypes);
                    builder.WriteInt32(peReader.PEHeaders.CoffHeader.TimeDateStamp);
                    builder.WriteInt32(peReader.PEHeaders.PEHeader.SizeOfImage);

                    var metadataReader   = peReader.GetMetadataReader();
                    var moduleDefinition = metadataReader.GetModuleDefinition();
                    builder.WriteGuid(metadataReader.GetGuid(moduleDefinition.Mvid));
                }
            }

            _debugMetadataOpt.AddCustomDebugInformation(
                parent: EntityHandle.ModuleDefinition,
                kind: _debugMetadataOpt.GetOrAddGuid(PortableCustomDebugInfoKinds.MetadataReferenceInfo),
                value: _debugMetadataOpt.GetOrAddBlob(builder));
Beispiel #33
0
 /// <summary>
 /// Write string as UTF8 with null terminator.
 /// </summary>
 private static void WriteUtf8String(BlobBuilder cmw, string str)
 {
     cmw.WriteUTF8(str);
     cmw.WriteByte(0);
 }
        public static bool WritePeToStream(
            EmitContext context,
            CommonMessageProvider messageProvider,
            Func <Stream> getPeStream,
            Func <Stream> getPortablePdbStreamOpt,
            PdbWriter nativePdbWriterOpt,
            string pdbPathOpt,
            bool allowMissingMethodBodies,
            bool isDeterministic,
            CancellationToken cancellationToken)
        {
            // If PDB writer is given, we have to have PDB path.
            Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null);

            var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, isDeterministic, getPortablePdbStreamOpt != null, cancellationToken);

            var properties = context.Module.Properties;

            nativePdbWriterOpt?.SetMetadataEmitter(mdWriter);

            // Since we are producing a full assembly, we should not have a module version ID
            // imposed ahead-of time. Instead we will compute a deterministic module version ID
            // based on the contents of the generated stream.
            Debug.Assert(properties.PersistentIdentifier == default(Guid));

            var ilBuilder = new BlobBuilder(32 * 1024);
            var mappedFieldDataBuilder = new BlobBuilder();
            var managedResourceBuilder = new BlobBuilder(1024);

            Blob mvidFixup;

            mdWriter.BuildMetadataAndIL(
                nativePdbWriterOpt,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                out mvidFixup);

            MethodDefinitionHandle entryPointHandle;
            MethodDefinitionHandle debugEntryPointHandle;

            mdWriter.GetEntryPoints(out entryPointHandle, out debugEntryPointHandle);

            if (!debugEntryPointHandle.IsNil)
            {
                nativePdbWriterOpt?.SetEntryPoint((uint)MetadataTokens.GetToken(debugEntryPointHandle));
            }

            if (nativePdbWriterOpt != null)
            {
                var assembly = mdWriter.Module.AsAssembly;
                if (assembly != null && assembly.Kind == OutputKind.WindowsRuntimeMetadata)
                {
                    // Dev12: If compiling to winmdobj, we need to add to PDB source spans of
                    //        all types and members for better error reporting by WinMDExp.
                    nativePdbWriterOpt.WriteDefinitionLocations(mdWriter.Module.GetSymbolToLocationMap());
                }
                else
                {
#if DEBUG
                    // validate that all definitions are writable
                    // if same scenario would happen in an winmdobj project
                    nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap());
#endif
                }
            }

            Stream peStream = getPeStream();
            if (peStream == null)
            {
                return(false);
            }

            ContentId nativePdbContentId = nativePdbWriterOpt?.GetContentId() ?? default(ContentId);

            // the writer shall not be used after this point for writing:
            nativePdbWriterOpt = null;

            var metadataSerializer = mdWriter.GetTypeSystemMetadataSerializer();

            var peBuilder = new PEBuilder(
                machine: properties.Machine,
                sectionAlignment: properties.SectionAlignment,
                fileAlignment: properties.FileAlignment,
                imageBase: properties.BaseAddress,
                majorLinkerVersion: properties.LinkerMajorVersion,
                minorLinkerVersion: properties.LinkerMinorVersion,
                majorOperatingSystemVersion: 4,
                minorOperatingSystemVersion: 0,
                majorImageVersion: 0,
                minorImageVersion: 0,
                majorSubsystemVersion: properties.MajorSubsystemVersion,
                minorSubsystemVersion: properties.MinorSubsystemVersion,
                subsystem: properties.Subsystem,
                dllCharacteristics: properties.DllCharacteristics,
                imageCharacteristics: properties.ImageCharacteristics,
                sizeOfStackReserve: properties.SizeOfStackReserve,
                sizeOfStackCommit: properties.SizeOfStackCommit,
                sizeOfHeapReserve: properties.SizeOfHeapReserve,
                sizeOfHeapCommit: properties.SizeOfHeapCommit,
                deterministicIdProvider: isDeterministic ? new Func <BlobBuilder, ContentId>(content => ContentId.FromHash(CryptographicHashProvider.ComputeSha1(content))) : null);

            ContentId portablePdbContentId;
            if (mdWriter.EmitStandaloneDebugMetadata)
            {
                Debug.Assert(getPortablePdbStreamOpt != null);

                var debugMetadataBuilder    = new BlobBuilder();
                var debugMetadataSerializer = mdWriter.GetStandaloneDebugMetadataSerializer(metadataSerializer.MetadataSizes, debugEntryPointHandle);
                debugMetadataSerializer.SerializeMetadata(debugMetadataBuilder, peBuilder.IdProvider, out portablePdbContentId);

                // write to Portable PDB stream:
                Stream portablePdbStream = getPortablePdbStreamOpt();
                if (portablePdbStream != null)
                {
                    debugMetadataBuilder.WriteContentTo(portablePdbStream);
                }
            }
            else
            {
                portablePdbContentId = default(ContentId);
            }

            var peDirectoriesBuilder = new PEDirectoriesBuilder();

            peBuilder.AddManagedSections(
                peDirectoriesBuilder,
                metadataSerializer,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                CreateNativeResourceSectionSerializer(context.Module),
                CalculateStrongNameSignatureSize(context.Module),
                entryPointHandle,
                pdbPathOpt,
                nativePdbContentId,
                portablePdbContentId,
                properties.CorFlags);

            var       peBlob = new BlobBuilder();
            ContentId peContentId;
            peBuilder.Serialize(peBlob, peDirectoriesBuilder, out peContentId);

            // Patch MVID
            if (!mvidFixup.IsDefault)
            {
                var mvidWriter = new BlobWriter(mvidFixup);
                mvidWriter.WriteBytes(peContentId.Guid);
                Debug.Assert(mvidWriter.RemainingBytes == 0);
            }

            try
            {
                peBlob.WriteContentTo(peStream);
            }
            catch (Exception e) when(!(e is OperationCanceledException))
            {
                throw new PeWritingException(e);
            }

            return(true);
        }
Beispiel #35
0
        public void WriteUTF16()
        {
            var writer = new BlobBuilder(4);

            writer.WriteUTF16("");
            writer.WriteUTF16("a");
            writer.WriteUTF16("");
            writer.WriteUTF16(new char[0]);

            writer.WriteUTF16(new char[] { '\ud800' });           // hi surrogate
            writer.WriteUTF16("\udc00");                          // lo surrogate
            writer.WriteUTF16("\ud800\udc00");                    // pair
            writer.WriteUTF16(new char[] { '\udc00', '\ud800' }); // lo + hi
            writer.WriteUTF16("\u1234");

            AssertEx.Equal(new byte[]
            {
                0x61, 0x00,
                0x00, 0xD8,
                0x00, 0xDC,
                0x00, 0xD8, 0x00, 0xDC,
                0x00, 0xDC, 0x00, 0xD8,
                0x34, 0x12
            }, writer.ToArray());
        }
Beispiel #36
0
        private static void SerializeDynamicLocalInfo(IMethodBody methodBody, ArrayBuilder <BlobBuilder> customDebugInfo)
        {
            if (!methodBody.HasDynamicLocalVariables)
            {
                return; //There are no dynamic locals
            }

            var dynamicLocals = ArrayBuilder <ILocalDefinition> .GetInstance();

            foreach (ILocalDefinition local in methodBody.LocalVariables)
            {
                Debug.Assert(local.SlotIndex >= 0);
                if (local.IsDynamic)
                {
                    dynamicLocals.Add(local);
                }
            }

            foreach (var currentScope in methodBody.LocalScopes)
            {
                foreach (var localConstant in currentScope.Constants)
                {
                    Debug.Assert(localConstant.SlotIndex < 0);
                    if (localConstant.IsDynamic)
                    {
                        dynamicLocals.Add(localConstant);
                    }
                }
            }

            Debug.Assert(dynamicLocals.Any()); // There must be at least one dynamic local if this point is reached

            const int dynamicAttributeSize = 64;
            const int identifierSize       = 64;
            const int blobSize             = dynamicAttributeSize + 4 + 4 + identifierSize * 2;//DynamicAttribute: 64, DynamicAttributeLength: 4, SlotIndex: 4, IdentifierName: 128
            var       cmw = new BlobBuilder();

            cmw.WriteByte(CDI.CdiVersion);
            cmw.WriteByte(CDI.CdiKindDynamicLocals);
            cmw.Align(4);
            // size = Version,Kind + size + cBuckets + (dynamicCount * sizeOf(Local Blob))
            cmw.WriteUInt32(4 + 4 + 4 + (uint)dynamicLocals.Count * blobSize);//Size of the Dynamic Block
            cmw.WriteUInt32((uint)dynamicLocals.Count);

            foreach (ILocalDefinition local in dynamicLocals)
            {
                if (local.Name.Length >= identifierSize)//Ignore and push empty information
                {
                    cmw.WriteBytes(0, blobSize);
                    continue;
                }

                var dynamicTransformFlags = local.DynamicTransformFlags;
                if (!dynamicTransformFlags.IsDefault && dynamicTransformFlags.Length <= dynamicAttributeSize)
                {
                    byte[] flag = new byte[dynamicAttributeSize];
                    for (int k = 0; k < dynamicTransformFlags.Length; k++)
                    {
                        if ((bool)dynamicTransformFlags[k].Value)
                        {
                            flag[k] = 1;
                        }
                    }
                    cmw.WriteBytes(flag);                                //Written Flag
                    cmw.WriteUInt32((uint)dynamicTransformFlags.Length); //Written Length
                }
                else
                {
                    cmw.WriteBytes(0, dynamicAttributeSize + 4); //Empty flag array and size.
                }

                var localIndex = local.SlotIndex;
                cmw.WriteUInt32((localIndex < 0) ? 0u : (uint)localIndex);

                char[] localName = new char[identifierSize];
                local.Name.CopyTo(0, localName, 0, local.Name.Length);
                cmw.WriteUTF16(localName);
            }

            dynamicLocals.Free();
            customDebugInfo.Add(cmw);
        }
Beispiel #37
0
        public void WriteUTF8_ReplaceUnpairedSurrogates()
        {
            var writer = new BlobBuilder(4);
            writer.WriteUTF8("a", allowUnpairedSurrogates: false);
            writer.WriteUTF8("", allowUnpairedSurrogates: false);
            writer.WriteUTF8("bc", allowUnpairedSurrogates: false);
            writer.WriteUTF8("d", allowUnpairedSurrogates: false);
            writer.WriteUTF8("", allowUnpairedSurrogates: false);

            writer.WriteUTF8(Encoding.UTF8.GetString(new byte[]
            {
                0x00,
                0xC2, 0x80,
                0xE1, 0x88, 0xB4
            }), allowUnpairedSurrogates: false);

            writer.WriteUTF8("\0\ud800", allowUnpairedSurrogates: false);       // hi surrogate
            writer.WriteUTF8("\0\udc00", allowUnpairedSurrogates: false);       // lo surrogate
            writer.WriteUTF8("\0\ud800\udc00", allowUnpairedSurrogates: false); // pair
            writer.WriteUTF8("\0\udc00\ud800", allowUnpairedSurrogates: false); // lo + hi

            AssertEx.Equal(new byte[]
            {
                (byte)'a',
                (byte)'b', (byte)'c',
                (byte)'d',
                0x00, 0xC2, 0x80, 0xE1, 0x88, 0xB4,

                0x00, 0xEF, 0xBF, 0xBD,
                0x00, 0xEF, 0xBF, 0xBD,
                0x00, 0xF0, 0x90, 0x80, 0x80,
                0x00, 0xEF, 0xBF, 0xBD, 0xEF, 0xBF, 0xBD
            }, writer.ToArray());
        }
Beispiel #38
0
        private BlobIdx SerializeSequencePoints(
            int localSignatureRowId,
            ImmutableArray <SequencePoint> sequencePoints,
            Dictionary <DebugSourceDocument, int> documentIndex,
            out int singleDocumentRowId)
        {
            if (sequencePoints.Length == 0)
            {
                singleDocumentRowId = 0;
                return(default(BlobIdx));
            }

            var writer = new BlobBuilder();

            int previousNonHiddenStartLine   = -1;
            int previousNonHiddenStartColumn = -1;

            // header:
            writer.WriteCompressedInteger((uint)localSignatureRowId);

            var previousDocument = TryGetSingleDocument(sequencePoints);

            singleDocumentRowId = (previousDocument != null) ? GetOrAddDocument(previousDocument, documentIndex) : 0;

            for (int i = 0; i < sequencePoints.Length; i++)
            {
                var currentDocument = sequencePoints[i].Document;
                if (previousDocument != currentDocument)
                {
                    int documentRowId = GetOrAddDocument(currentDocument, documentIndex);

                    // optional document in header or document record:
                    if (previousDocument != null)
                    {
                        writer.WriteCompressedInteger(0);
                    }

                    writer.WriteCompressedInteger((uint)documentRowId);
                    previousDocument = currentDocument;
                }

                // delta IL offset:
                if (i > 0)
                {
                    writer.WriteCompressedInteger((uint)(sequencePoints[i].Offset - sequencePoints[i - 1].Offset));
                }
                else
                {
                    writer.WriteCompressedInteger((uint)sequencePoints[i].Offset);
                }

                if (sequencePoints[i].IsHidden)
                {
                    writer.WriteInt16(0);
                    continue;
                }

                // Delta Lines & Columns:
                SerializeDeltaLinesAndColumns(writer, sequencePoints[i]);

                // delta Start Lines & Columns:
                if (previousNonHiddenStartLine < 0)
                {
                    Debug.Assert(previousNonHiddenStartColumn < 0);
                    writer.WriteCompressedInteger((uint)sequencePoints[i].StartLine);
                    writer.WriteCompressedInteger((uint)sequencePoints[i].StartColumn);
                }
                else
                {
                    writer.WriteCompressedSignedInteger(sequencePoints[i].StartLine - previousNonHiddenStartLine);
                    writer.WriteCompressedSignedInteger(sequencePoints[i].StartColumn - previousNonHiddenStartColumn);
                }

                previousNonHiddenStartLine   = sequencePoints[i].StartLine;
                previousNonHiddenStartColumn = sequencePoints[i].StartColumn;
            }

            return(_debugHeapsOpt.GetBlobIndex(writer));
        }
Beispiel #39
0
        private void WriteHeaders(Stream peStream, NtHeader ntHeader, CoffHeader coffHeader, List<SectionHeader> sectionHeaders, out long ntHeaderTimestampPosition)
        {
            var writer = new BlobBuilder(1024);

            // MS-DOS stub (128 bytes)
            writer.WriteBytes(s_dosHeader);

            // PE Signature "PE\0\0" 
            writer.WriteUInt32(0x00004550);

            // COFF Header (20 bytes)
            writer.WriteUInt16((ushort)coffHeader.Machine);
            writer.WriteUInt16((ushort)coffHeader.NumberOfSections);
            ntHeaderTimestampPosition = writer.Position + peStream.Position;
            writer.WriteUInt32((uint)coffHeader.TimeDateStamp);
            writer.WriteUInt32((uint)coffHeader.PointerToSymbolTable);
            writer.WriteUInt32((uint)coffHeader.NumberOfSymbols);
            writer.WriteUInt16((ushort)(_is32bit ? 224 : 240)); // SizeOfOptionalHeader
            writer.WriteUInt16((ushort)coffHeader.Characteristics);

            // PE Headers:
            writer.WriteUInt16((ushort)(_is32bit ? PEMagic.PE32 : PEMagic.PE32Plus)); // 2
            writer.WriteByte(ntHeader.MajorLinkerVersion); // 3
            writer.WriteByte(ntHeader.MinorLinkerVersion); // 4
            writer.WriteUInt32((uint)ntHeader.SizeOfCode); // 8
            writer.WriteUInt32((uint)ntHeader.SizeOfInitializedData); // 12
            writer.WriteUInt32((uint)ntHeader.SizeOfUninitializedData); // 16
            writer.WriteUInt32((uint)ntHeader.AddressOfEntryPoint); // 20
            writer.WriteUInt32((uint)ntHeader.BaseOfCode); // 24

            if (_is32bit)
            {
                writer.WriteUInt32((uint)ntHeader.BaseOfData); // 28
                writer.WriteUInt32((uint)ntHeader.ImageBase); // 32
            }
            else
            {
                writer.WriteUInt64(ntHeader.ImageBase); // 32
            }

            // NT additional fields:
            writer.WriteUInt32((uint)ntHeader.SectionAlignment); // 36
            writer.WriteUInt32((uint)ntHeader.FileAlignment); // 40
            writer.WriteUInt16(ntHeader.MajorOperatingSystemVersion); // 42
            writer.WriteUInt16(ntHeader.MinorOperatingSystemVersion); // 44
            writer.WriteUInt16(ntHeader.MajorImageVersion); // 46
            writer.WriteUInt16(ntHeader.MinorImageVersion); // 48
            writer.WriteUInt16(ntHeader.MajorSubsystemVersion); // MajorSubsystemVersion 50
            writer.WriteUInt16(ntHeader.MinorSubsystemVersion); // MinorSubsystemVersion 52

            // Win32VersionValue (reserved, should be 0)
            writer.WriteUInt32(0); // 56

            writer.WriteUInt32((uint)ntHeader.SizeOfImage); // 60
            writer.WriteUInt32((uint)ntHeader.SizeOfHeaders); // 64
            writer.WriteUInt32(ntHeader.Checksum); // 68            
            writer.WriteUInt16((ushort)ntHeader.Subsystem); // 70
            writer.WriteUInt16((ushort)ntHeader.DllCharacteristics);

            if (_is32bit)
            {
                writer.WriteUInt32((uint)ntHeader.SizeOfStackReserve); // 76
                writer.WriteUInt32((uint)ntHeader.SizeOfStackCommit); // 80
                writer.WriteUInt32((uint)ntHeader.SizeOfHeapReserve); // 84
                writer.WriteUInt32((uint)ntHeader.SizeOfHeapCommit); // 88
            }
            else
            {
                writer.WriteUInt64(ntHeader.SizeOfStackReserve); // 80
                writer.WriteUInt64(ntHeader.SizeOfStackCommit); // 88
                writer.WriteUInt64(ntHeader.SizeOfHeapReserve); // 96
                writer.WriteUInt64(ntHeader.SizeOfHeapCommit); // 104
            }

            // LoaderFlags
            writer.WriteUInt32(0); // 92|108

            // The number of data-directory entries in the remainder of the header.
            writer.WriteUInt32(16); //  96|112

            // directory entries:
            writer.WriteUInt32((uint)ntHeader.ExportTable.RelativeVirtualAddress); // 100|116
            writer.WriteUInt32((uint)ntHeader.ExportTable.Size); // 104|120
            writer.WriteUInt32((uint)ntHeader.ImportTable.RelativeVirtualAddress); // 108|124
            writer.WriteUInt32((uint)ntHeader.ImportTable.Size); // 112|128
            writer.WriteUInt32((uint)ntHeader.ResourceTable.RelativeVirtualAddress); // 116|132
            writer.WriteUInt32((uint)ntHeader.ResourceTable.Size); // 120|136
            writer.WriteUInt32((uint)ntHeader.ExceptionTable.RelativeVirtualAddress); // 124|140
            writer.WriteUInt32((uint)ntHeader.ExceptionTable.Size); // 128|144
            writer.WriteUInt32((uint)ntHeader.CertificateTable.RelativeVirtualAddress); // 132|148
            writer.WriteUInt32((uint)ntHeader.CertificateTable.Size); // 136|152
            writer.WriteUInt32((uint)ntHeader.BaseRelocationTable.RelativeVirtualAddress); // 140|156
            writer.WriteUInt32((uint)ntHeader.BaseRelocationTable.Size); // 144|160
            writer.WriteUInt32((uint)ntHeader.DebugTable.RelativeVirtualAddress); // 148|164
            writer.WriteUInt32((uint)ntHeader.DebugTable.Size); // 152|168
            writer.WriteUInt32((uint)ntHeader.CopyrightTable.RelativeVirtualAddress); // 156|172
            writer.WriteUInt32((uint)ntHeader.CopyrightTable.Size); // 160|176
            writer.WriteUInt32((uint)ntHeader.GlobalPointerTable.RelativeVirtualAddress); // 164|180
            writer.WriteUInt32((uint)ntHeader.GlobalPointerTable.Size); // 168|184
            writer.WriteUInt32((uint)ntHeader.ThreadLocalStorageTable.RelativeVirtualAddress); // 172|188
            writer.WriteUInt32((uint)ntHeader.ThreadLocalStorageTable.Size); // 176|192
            writer.WriteUInt32((uint)ntHeader.LoadConfigTable.RelativeVirtualAddress); // 180|196
            writer.WriteUInt32((uint)ntHeader.LoadConfigTable.Size); // 184|200
            writer.WriteUInt32((uint)ntHeader.BoundImportTable.RelativeVirtualAddress); // 188|204
            writer.WriteUInt32((uint)ntHeader.BoundImportTable.Size); // 192|208
            writer.WriteUInt32((uint)ntHeader.ImportAddressTable.RelativeVirtualAddress); // 196|212
            writer.WriteUInt32((uint)ntHeader.ImportAddressTable.Size); // 200|216
            writer.WriteUInt32((uint)ntHeader.DelayImportTable.RelativeVirtualAddress); // 204|220
            writer.WriteUInt32((uint)ntHeader.DelayImportTable.Size); // 208|224
            writer.WriteUInt32((uint)ntHeader.CliHeaderTable.RelativeVirtualAddress); // 212|228
            writer.WriteUInt32((uint)ntHeader.CliHeaderTable.Size); // 216|232
            writer.WriteUInt64(0); // 224|240

            // Section Headers
            foreach (var sectionHeader in sectionHeaders)
            {
                WriteSectionHeader(sectionHeader, writer);
            }

            writer.WriteTo(peStream);
        }
Beispiel #40
0
 private static void SerializeTupleElementNames(ArrayBuilder <LocalAndScope> locals, BlobBuilder cmw)
 {
     cmw.WriteInt32(locals.Count);
     foreach (var localAndScope in locals)
     {
         var local             = localAndScope.Local;
         var scope             = localAndScope.Scope;
         var tupleElementNames = local.TupleElementNames;
         cmw.WriteInt32(tupleElementNames.Length);
         foreach (var tupleElementName in tupleElementNames)
         {
             WriteUtf8String(cmw, (string)tupleElementName.Value ?? string.Empty);
         }
         cmw.WriteInt32(local.SlotIndex);
         cmw.WriteInt32(scope.StartOffset);
         cmw.WriteInt32(scope.EndOffset);
         WriteUtf8String(cmw, local.Name);
     }
 }
Beispiel #41
0
        private void WriteTextSection(
            Stream peStream,
            SectionHeader textSection,
            int importTableRva,
            int importAddressTableRva,
            int entryPointToken,
            BlobBuilder metadataWriter,
            BlobBuilder ilWriter,
            BlobBuilder mappedFieldDataWriter,
            BlobBuilder managedResourceWriter,
            MetadataSizes metadataSizes,
            ContentId nativePdbContentId,
            ContentId portablePdbContentId,
            out long metadataPosition)
        {
            // TODO: zero out all bytes:
            peStream.Position = textSection.PointerToRawData;

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

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

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

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

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

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

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

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

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

            // TODO: zero out all bytes:
            int alignedPosition = textSection.PointerToRawData + textSection.SizeOfRawData;
            if (peStream.Position != alignedPosition)
            {
                peStream.Position = alignedPosition - 1;
                peStream.WriteByte(0);
            }
        }
Beispiel #42
0
        private void SerializeImport(BlobBuilder writer, UsedNamespaceOrType import)
        {
            if (import.TargetXmlNamespaceOpt != null)
            {
                Debug.Assert(import.TargetNamespaceOpt == null);
                Debug.Assert(import.TargetAssemblyOpt == null);
                Debug.Assert(import.TargetTypeOpt == null);

                // <import> ::= ImportXmlNamespace <alias> <target-namespace>
                writer.WriteByte((byte)ImportDefinitionKind.ImportXmlNamespace);
                writer.WriteCompressedInteger((uint)_debugHeapsOpt.ResolveBlobIndex(_debugHeapsOpt.GetBlobIndexUtf8(import.AliasOpt)));
                writer.WriteCompressedInteger((uint)_debugHeapsOpt.ResolveBlobIndex(_debugHeapsOpt.GetBlobIndexUtf8(import.TargetXmlNamespaceOpt)));
            }
            else if (import.TargetTypeOpt != null)
            {
                Debug.Assert(import.TargetNamespaceOpt == null);
                Debug.Assert(import.TargetAssemblyOpt == null);

                if (import.AliasOpt != null)
                {
                    // <import> ::= AliasType <alias> <target-type>
                    writer.WriteByte((byte)ImportDefinitionKind.AliasType);
                    writer.WriteCompressedInteger((uint)_debugHeapsOpt.ResolveBlobIndex(_debugHeapsOpt.GetBlobIndexUtf8(import.AliasOpt)));
                }
                else
                {
                    // <import> ::= ImportType <target-type>
                    writer.WriteByte((byte)ImportDefinitionKind.ImportType);
                }

                writer.WriteCompressedInteger(GetTypeDefOrRefCodedIndex(import.TargetTypeOpt, treatRefAsPotentialTypeSpec: true)); // TODO: index in release build
            }
            else if (import.TargetNamespaceOpt != null)
            {
                if (import.TargetAssemblyOpt != null)
                {
                    if (import.AliasOpt != null)
                    {
                        // <import> ::= AliasAssemblyNamespace <alias> <target-assembly> <target-namespace>
                        writer.WriteByte((byte)ImportDefinitionKind.AliasAssemblyNamespace);
                        writer.WriteCompressedInteger((uint)_debugHeapsOpt.ResolveBlobIndex(_debugHeapsOpt.GetBlobIndexUtf8(import.AliasOpt)));
                    }
                    else
                    {
                        // <import> ::= ImportAssemblyNamespace <target-assembly> <target-namespace>
                        writer.WriteByte((byte)ImportDefinitionKind.ImportAssemblyNamespace);
                    }

                    writer.WriteCompressedInteger((uint)GetAssemblyRefIndex(import.TargetAssemblyOpt));
                }
                else
                {
                    if (import.AliasOpt != null)
                    {
                        // <import> ::= AliasNamespace <alias> <target-namespace>
                        writer.WriteByte((byte)ImportDefinitionKind.AliasNamespace);
                        writer.WriteCompressedInteger((uint)_debugHeapsOpt.ResolveBlobIndex(_debugHeapsOpt.GetBlobIndexUtf8(import.AliasOpt)));
                    }
                    else
                    {
                        // <import> ::= ImportNamespace <target-namespace>
                        writer.WriteByte((byte)ImportDefinitionKind.ImportNamespace);
                    }
                }

                // TODO: cache?
                string namespaceName = TypeNameSerializer.BuildQualifiedNamespaceName(import.TargetNamespaceOpt);
                writer.WriteCompressedInteger((uint)_debugHeapsOpt.ResolveBlobIndex(_debugHeapsOpt.GetBlobIndexUtf8(namespaceName)));
            }
            else
            {
                // <import> ::= ImportReferenceAlias <alias>
                Debug.Assert(import.AliasOpt != null);
                Debug.Assert(import.TargetAssemblyOpt == null);

                writer.WriteByte((byte)ImportDefinitionKind.ImportAssemblyReferenceAlias);
                writer.WriteCompressedInteger((uint)_debugHeapsOpt.ResolveBlobIndex(_debugHeapsOpt.GetBlobIndexUtf8(import.AliasOpt)));
            }
        }
Beispiel #43
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.Length == SizeOfImportTable);

            writer.WriteTo(peStream);
        }
Beispiel #44
0
        private BlobIdx SerializeLocalConstantSignature(ILocalDefinition localConstant)
        {
            var writer = new BlobBuilder();

            // CustomMod*
            SerializeCustomModifiers(localConstant.CustomModifiers, writer);

            var type     = localConstant.Type;
            var typeCode = type.TypeCode(Context);

            object value = localConstant.CompileTimeValue.Value;

            // PrimitiveConstant or EnumConstant
            if (value is decimal)
            {
                writer.WriteByte(0x11);
                writer.WriteCompressedInteger(GetTypeDefOrRefCodedIndex(type, treatRefAsPotentialTypeSpec: true));

                writer.WriteDecimal((decimal)value);
            }
            else if (value is DateTime)
            {
                writer.WriteByte(0x11);
                writer.WriteCompressedInteger(GetTypeDefOrRefCodedIndex(type, treatRefAsPotentialTypeSpec: true));

                writer.WriteDateTime((DateTime)value);
            }
            else if (typeCode == PrimitiveTypeCode.String)
            {
                writer.WriteByte((byte)ConstantTypeCode.String);
                if (value == null)
                {
                    writer.WriteByte(0xff);
                }
                else
                {
                    writer.WriteUTF16((string)value);
                }
            }
            else if (value != null)
            {
                // TypeCode
                writer.WriteByte((byte)GetConstantTypeCode(value));

                // Value
                writer.WriteConstant(value);

                // EnumType
                if (type.IsEnum)
                {
                    writer.WriteCompressedInteger(GetTypeDefOrRefCodedIndex(type, treatRefAsPotentialTypeSpec: true));
                }
            }
            else if (this.module.IsPlatformType(type, PlatformType.SystemObject))
            {
                writer.WriteByte(0x1c);
            }
            else
            {
                writer.WriteByte((byte)(type.IsValueType ? 0x11 : 0x12));
                writer.WriteCompressedInteger(GetTypeDefOrRefCodedIndex(type, treatRefAsPotentialTypeSpec: true));
            }

            return(_debugHeapsOpt.GetBlobIndex(writer));
        }
Beispiel #45
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.Length == CorHeaderSize);
            Debug.Assert(writer.Length % 4 == 0);

            writer.WriteTo(peStream);
        }
Beispiel #46
0
 /// <summary>
 /// Write string as UTF16 with null terminator.
 /// </summary>
 private static void WriteUtf16String(BlobBuilder cmw, string str)
 {
     cmw.WriteUTF16(str);
     cmw.WriteUInt16(0);
 }
Beispiel #47
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.WriteTo(peStream);
        }
Beispiel #48
0
        private static void TestCompressedSignedInteger(byte[] expected, int value)
        {
            var writer = new BlobWriter(4);
            writer.WriteCompressedSignedInteger(value);
            AssertEx.Equal(expected, writer.ToArray());

            var builder = new BlobBuilder();
            builder.WriteCompressedSignedInteger(value);
            AssertEx.Equal(expected, builder.ToArray());
        }
Beispiel #49
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.Length % 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;
                    }
                }
            }
        }
Beispiel #50
0
        public void WriteBytes1()
        {
            var writer = new BlobBuilder(4);

            writer.WriteBytes(new byte[] { 1, 2, 3, 4 });
            writer.WriteBytes(new byte[] { });
            writer.WriteBytes(new byte[] { }, 0, 0);
            writer.WriteBytes(new byte[] { 5, 6, 7, 8 });
            writer.WriteBytes(new byte[] { 9 });
            writer.WriteBytes(new byte[] { 0x0a }, 0, 0);
            writer.WriteBytes(new byte[] { 0x0b }, 0, 1);
            writer.WriteBytes(new byte[] { 0x0c }, 1, 0);
            writer.WriteBytes(new byte[] { 0x0d, 0x0e }, 1, 1);

            AssertEx.Equal(new byte[]
            {
                0x01, 0x02, 0x03, 0x04,
                0x05, 0x06, 0x07, 0x08,
                0x09,
                0x0b,
                0x0e
            }, writer.ToArray());
        }
 private BlobHandle GetOrAddBlob(BlobBuilder builder)
 {
     // TODO: avoid making a copy if the blob exists in the index
     return(GetOrAddBlob(builder.ToImmutableArray()));
 }
        private BlobHandle SerializeLocalConstantSignature(ILocalDefinition localConstant)
        {
            var builder = new BlobBuilder();

            // TODO: BlobEncoder.LocalConstantSignature

            // CustomMod*
            var encoder = new CustomModifiersEncoder(builder);

            SerializeCustomModifiers(encoder, localConstant.CustomModifiers);

            var type     = localConstant.Type;
            var typeCode = type.TypeCode;

            object value = localConstant.CompileTimeValue.Value;

            // PrimitiveConstant or EnumConstant
            if (value is decimal)
            {
                builder.WriteByte((byte)SignatureTypeKind.ValueType);
                builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(type)));

                builder.WriteDecimal((decimal)value);
            }
            else if (value is DateTime)
            {
                builder.WriteByte((byte)SignatureTypeKind.ValueType);
                builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(type)));

                builder.WriteDateTime((DateTime)value);
            }
            else if (typeCode == PrimitiveTypeCode.String)
            {
                builder.WriteByte((byte)ConstantTypeCode.String);
                if (value == null)
                {
                    builder.WriteByte(0xff);
                }
                else
                {
                    builder.WriteUTF16((string)value);
                }
            }
            else if (value != null)
            {
                // TypeCode
                builder.WriteByte((byte)GetConstantTypeCode(value));

                // Value
                builder.WriteConstant(value);

                // EnumType
                if (type.IsEnum)
                {
                    builder.WriteCompressedInteger(
                        CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(type))
                        );
                }
            }
            else if (this.module.IsPlatformType(type, PlatformType.SystemObject))
            {
                builder.WriteByte((byte)SignatureTypeCode.Object);
            }
            else
            {
                builder.WriteByte(
                    (byte)(type.IsValueType ? SignatureTypeKind.ValueType : SignatureTypeKind.Class)
                    );
                builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(type)));
            }

            return(_debugMetadataOpt.GetOrAddBlob(builder));
        }