예제 #1
0
파일: BlobTests.cs 프로젝트: rgani/roslyn
        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());
        }
예제 #2
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());
        }
예제 #3
0
파일: BlobTests.cs 프로젝트: rgani/roslyn
        public void WriteContentToBlobBuilder()
        {
            var builder1 = new BlobBuilder(16);
            for (int i = 0; i < 20; i++)
            {
                builder1.WriteByte((byte)i);
            }

            var builder2 = new BlobBuilder(256);
            builder1.WriteContentTo(builder2);
            AssertEx.Equal(new byte[]
            {
                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13
            }, builder2.ToArray());

            builder1.WriteByte(0xff);

            builder1.WriteContentTo(builder2);
            AssertEx.Equal(new byte[]
            {
                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
                0xff,
            }, builder2.ToArray());
        }
예제 #4
0
파일: BlobTests.cs 프로젝트: rgani/roslyn
        public void WriteContentToStream_Errors()
        {
            var builder = new BlobBuilder(16);
            builder.WriteByte(1);

            Assert.Throws<ArgumentNullException>(() => builder.WriteContentTo((Stream)null));
            Assert.Throws<NotSupportedException>(() => builder.WriteContentTo(new MemoryStream(new byte[] { 1 }, writable: false)));
        }
예제 #5
0
파일: BlobTests.cs 프로젝트: rgani/roslyn
        public void ToImmutableArray_Errors()
        {
            var builder = new BlobBuilder(16);
            builder.WriteByte(1);

            Assert.Throws<ArgumentOutOfRangeException>(() => builder.ToImmutableArray(-1, 0));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.ToImmutableArray(0, -1));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.ToImmutableArray(0, 2));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.ToImmutableArray(1, 1));
        }
예제 #6
0
파일: BlobTests.cs 프로젝트: rgani/roslyn
        public void ToArray2()
        {
            var builder = new BlobBuilder(16);

            AssertEx.Equal(new byte[] { }, builder.ToArray(0, 0));

            for (int i = 0; i < 34; i++)
            {
                builder.WriteByte((byte)i);
            }

            AssertEx.Equal(new byte[]
            {
                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
                0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
                0x20, 0x21
            }, builder.ToArray());

            AssertEx.Equal(new byte[]
            {
                0x0E, 0x0F,
                0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
                0x20, 0x21
            }, builder.ToArray(0x0e, 20));

            AssertEx.Equal(new byte[] { 0x0E }, builder.ToArray(0x0e, 1));
            AssertEx.Equal(new byte[] { 0x0E, 0x0F }, builder.ToArray(0x0e, 2));
            AssertEx.Equal(new byte[] { 0x0E, 0x0F, 0x10 }, builder.ToArray(0x0e, 3));
            AssertEx.Equal(new byte[] { 0x0E, 0x0F, 0x10, 0x11 }, builder.ToArray(0x0e, 4));

            AssertEx.Equal(new byte[] { 0x1E }, builder.ToArray(0x1e, 1));
            AssertEx.Equal(new byte[] { 0x1E, 0x1F }, builder.ToArray(0x1e, 2));
            AssertEx.Equal(new byte[] { 0x1E, 0x1F, 0x20 }, builder.ToArray(0x1e, 3));
            AssertEx.Equal(new byte[] { 0x1E, 0x1F, 0x20, 0x21 }, builder.ToArray(0x1e, 4));
        }
예제 #7
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);
        }
예제 #8
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);
        }
예제 #9
0
 private void SerializeReferenceToPreviousMethodWithUsingInfo(ArrayBuilder<BlobBuilder> customDebugInfo)
 {
     BlobBuilder cmw = new BlobBuilder(12);
     cmw.WriteByte(CDI.CdiVersion);
     cmw.WriteByte(CDI.CdiKindForwardInfo);
     cmw.Align(4);
     cmw.WriteUInt32(12);
     cmw.WriteUInt32((uint)_previousMethodTokenWithUsingInfo);
     customDebugInfo.Add(cmw);
 }
예제 #10
0
        private void SerializeNamespaceScopeMetadata(EmitContext context, IMethodBody methodBody, ArrayBuilder<BlobBuilder> customDebugInfo)
        {
            if (context.Module.GenerateVisualBasicStylePdb)
            {
                return;
            }

            if (ShouldForwardToPreviousMethodWithUsingInfo(context, methodBody))
            {
                Debug.Assert(!ReferenceEquals(_previousMethodBodyWithUsingInfo, methodBody));
                SerializeReferenceToPreviousMethodWithUsingInfo(customDebugInfo);
                return;
            }

            List<ushort> usingCounts = new List<ushort>();
            var cmw = new BlobBuilder();
            for (IImportScope scope = methodBody.ImportScope; scope != null; scope = scope.Parent)
            {
                usingCounts.Add((ushort)scope.GetUsedNamespaces().Length);
            }

            // ACASEY: This originally wrote (uint)12, (ushort)1, (ushort)0 in the
            // case where usingCounts was empty, but I'm not sure why.
            if (usingCounts.Count > 0)
            {
                uint streamLength;
                cmw.WriteByte(CDI.CdiVersion);
                cmw.WriteByte(CDI.CdiKindUsingInfo);
                cmw.Align(4);

                cmw.WriteUInt32(streamLength = BitArithmeticUtilities.Align((uint)usingCounts.Count * 2 + 10, 4));
                cmw.WriteUInt16((ushort)usingCounts.Count);
                foreach (ushort uc in usingCounts)
                {
                    cmw.WriteUInt16(uc);
                }

                cmw.Align(4);
                Debug.Assert(streamLength == cmw.Length);
                customDebugInfo.Add(cmw);
            }

            if (_methodBodyWithModuleInfo != null && !ReferenceEquals(_methodBodyWithModuleInfo, methodBody))
            {
                SerializeReferenceToMethodWithModuleInfo(customDebugInfo);
            }
        }
예제 #11
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)
            {
                if (local.IsDynamic)
                {
                    dynamicLocals.Add(local);
                }
            }

            int dynamicVariableCount = dynamicLocals.Count;

            foreach (var currentScope in methodBody.LocalScopes)
            {
                foreach (var localConstant in currentScope.Constants)
                {
                    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 blobSize = 200;//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);

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

                var dynamicTransformFlags = local.DynamicTransformFlags;
                if (!dynamicTransformFlags.IsDefault && dynamicTransformFlags.Length <= 64)
                {
                    byte[] flag = new byte[64];
                    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, 68); //Empty flag array and size.
                }

                if (localIndex < dynamicVariableCount)
                {
                    // Dynamic variable
                    cmw.WriteUInt32((uint)local.SlotIndex);
                }
                else
                {
                    // Dynamic constant
                    cmw.WriteUInt32(0);
                }

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

                localIndex++;
            }

            dynamicLocals.Free();
            customDebugInfo.Add(cmw);
        }
예제 #12
0
        private static void SerializeStateMachineLocalScopes(IMethodBody methodBody, ArrayBuilder<BlobBuilder> customDebugInfo)
        {
            var scopes = methodBody.StateMachineHoistedLocalScopes;
            if (scopes.IsDefaultOrEmpty)
            {
                return;
            }

            uint numberOfScopes = (uint)scopes.Length;
            var cmw = new BlobBuilder();
            cmw.WriteByte(CDI.CdiVersion);
            cmw.WriteByte(CDI.CdiKindStateMachineHoistedLocalScopes);
            cmw.Align(4);
            cmw.WriteUInt32(12 + numberOfScopes * 8);
            cmw.WriteUInt32(numberOfScopes);
            foreach (var scope in scopes)
            {
                if (scope.IsDefault)
                {
                    cmw.WriteUInt32(0);
                    cmw.WriteUInt32(0);
                }
                else
                {
                    // Dev12 C# emits end-inclusive range
                    cmw.WriteUInt32((uint)scope.StartOffset);
                    cmw.WriteUInt32((uint)scope.EndOffset - 1);
                }
            }

            customDebugInfo.Add(cmw);
        }
예제 #13
0
 private static void SerializeReferenceToIteratorClass(string iteratorClassName, ArrayBuilder<BlobBuilder> customDebugInfo)
 {
     if (iteratorClassName == null) return;
     var cmw = new BlobBuilder();
     cmw.WriteByte(CDI.CdiVersion);
     cmw.WriteByte(CDI.CdiKindForwardIterator);
     cmw.Align(4);
     uint length = 10 + (uint)iteratorClassName.Length * 2;
     if ((length & 3) != 0) length += 4 - (length & 3);
     cmw.WriteUInt32(length);
     cmw.WriteUTF16(iteratorClassName);
     cmw.WriteInt16(0);
     cmw.Align(4);
     Debug.Assert(cmw.Position == length);
     customDebugInfo.Add(cmw);
 }
예제 #14
0
        private static BlobBuilder SerializeRecord(byte kind, Action<BlobBuilder> data)
        {
            var cmw = new BlobBuilder();
            cmw.WriteByte(CDI.CdiVersion);
            cmw.WriteByte(kind);
            cmw.WriteByte(0);

            // alignment size (will be patched)
            int alignmentSizeAndLengthPosition = cmw.Position;
            cmw.WriteByte(0);

            // length (will be patched)
            cmw.WriteUInt32(0);

            data(cmw);

            int length = cmw.Position;
            int alignedLength = 4 * ((length + 3) / 4);
            byte alignmentSize = (byte)(alignedLength - length);

            for (int i = 0; i < alignmentSize; i++)
            {
                cmw.WriteByte(0);
            }

            cmw.SetPosition(alignmentSizeAndLengthPosition);
            cmw.WriteByte(alignmentSize);
            cmw.WriteUInt32((uint)alignedLength);

            cmw.SetPosition(length);
            return cmw;
        }
예제 #15
0
파일: BlobTests.cs 프로젝트: rgani/roslyn
        public void Link()
        {
            var builder1 = new BlobBuilder(16);
            builder1.WriteByte(1);

            var builder2 = new BlobBuilder(16);
            builder2.WriteByte(2);

            var builder3 = new BlobBuilder(16);
            builder3.WriteByte(3);

            var builder4 = new BlobBuilder(16);
            builder4.WriteByte(4);

            var builder5 = new BlobBuilder(16);
            builder5.WriteByte(5);

            builder2.LinkPrefix(builder1);
            AssertEx.Equal(new byte[] { 1, 2 }, builder2.ToArray());
            Assert.Throws<InvalidOperationException>(() => builder1.ToArray());
            Assert.Throws<InvalidOperationException>(() => builder2.LinkPrefix(builder1));
            Assert.Throws<InvalidOperationException>(() => builder1.WriteByte(0xff));
            Assert.Throws<InvalidOperationException>(() => builder1.WriteBytes(1, 10));
            Assert.Throws<InvalidOperationException>(() => builder1.WriteBytes(new byte[] { 1 }));
            Assert.Throws<InvalidOperationException>(() => builder1.ReserveBytes(1));
            Assert.Throws<InvalidOperationException>(() => builder1.GetBlobs());
            Assert.Throws<InvalidOperationException>(() => builder1.ContentEquals(builder1));
            Assert.Throws<InvalidOperationException>(() => builder1.WriteUTF16("str"));
            Assert.Throws<InvalidOperationException>(() => builder1.WriteUTF8("str", allowUnpairedSurrogates: false));

            builder2.LinkSuffix(builder3);
            AssertEx.Equal(new byte[] { 1, 2, 3 }, builder2.ToArray());
            Assert.Throws<InvalidOperationException>(() => builder3.LinkPrefix(builder5));

            builder2.LinkPrefix(builder4);
            AssertEx.Equal(new byte[] { 4, 1, 2, 3 }, builder2.ToArray());
            Assert.Throws<InvalidOperationException>(() => builder4.LinkPrefix(builder5));

            builder2.LinkSuffix(builder5);
            AssertEx.Equal(new byte[] { 4, 1, 2, 3, 5 }, builder2.ToArray());
        }
예제 #16
0
파일: BlobTests.cs 프로젝트: rgani/roslyn
        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();
        }
예제 #17
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));
        }
예제 #18
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);
        }
예제 #19
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)));
            }
        }
        private static BlobBuilder SerializeRecord(byte kind, Action<BlobBuilder> data)
        {
            var cmw = new BlobBuilder();
            cmw.WriteByte(CDI.CdiVersion);
            cmw.WriteByte(kind);
            cmw.WriteByte(0);

            // alignment size and length (will be patched)
            var alignmentSizeAndLengthWriter = cmw.ReserveBytes(sizeof(byte) + sizeof(uint));

            data(cmw);

            int length = cmw.Position;
            int alignedLength = 4 * ((length + 3) / 4);
            byte alignmentSize = (byte)(alignedLength - length);
            cmw.WriteBytes(0, alignmentSize);

            // fill in alignment size and length:
            alignmentSizeAndLengthWriter.WriteByte(alignmentSize);
            alignmentSizeAndLengthWriter.WriteUInt32((uint)alignedLength);

            return cmw;
        }
        private void EmbedCompilationOptions(CommonPEModuleBuilder module)
        {
            var builder = new BlobBuilder();

            var compilerVersion = typeof(Compilation).Assembly.GetCustomAttribute <AssemblyInformationalVersionAttribute>().InformationalVersion;

            WriteValue(CompilationOptionNames.CompilationOptionsVersion, CompilationOptionsSchemaVersion.ToString());
            WriteValue(CompilationOptionNames.CompilerVersion, compilerVersion);

            WriteValue(CompilationOptionNames.Language, module.CommonCompilation.Options.Language);
            WriteValue(CompilationOptionNames.SourceFileCount, module.CommonCompilation.SyntaxTrees.Count().ToString());

            if (module.EmitOptions.FallbackSourceFileEncoding != null)
            {
                WriteValue(CompilationOptionNames.FallbackEncoding, module.EmitOptions.FallbackSourceFileEncoding.WebName);
            }

            if (module.EmitOptions.DefaultSourceFileEncoding != null)
            {
                WriteValue(CompilationOptionNames.DefaultEncoding, module.EmitOptions.DefaultSourceFileEncoding.WebName);
            }

            int portabilityPolicy = 0;

            if (module.CommonCompilation.Options.AssemblyIdentityComparer is DesktopAssemblyIdentityComparer identityComparer)
            {
                portabilityPolicy |= identityComparer.PortabilityPolicy.SuppressSilverlightLibraryAssembliesPortability ? 0b1 : 0;
                portabilityPolicy |= identityComparer.PortabilityPolicy.SuppressSilverlightPlatformAssembliesPortability ? 0b10 : 0;
            }

            if (portabilityPolicy != 0)
            {
                WriteValue(CompilationOptionNames.PortabilityPolicy, portabilityPolicy.ToString());
            }

            var optimizationLevel = module.CommonCompilation.Options.OptimizationLevel;
            var debugPlusMode     = module.CommonCompilation.Options.DebugPlusMode;

            if (optimizationLevel != OptimizationLevel.Debug || debugPlusMode)
            {
                WriteValue(CompilationOptionNames.Optimization, optimizationLevel.ToPdbSerializedString(debugPlusMode));
            }

            var runtimeVersion = typeof(object).Assembly.GetCustomAttribute <AssemblyInformationalVersionAttribute>()?.InformationalVersion;

            WriteValue(CompilationOptionNames.RuntimeVersion, runtimeVersion);

            module.CommonCompilation.SerializePdbEmbeddedCompilationOptions(builder);

            _debugMetadataOpt.AddCustomDebugInformation(
                parent: EntityHandle.ModuleDefinition,
                kind: _debugMetadataOpt.GetOrAddGuid(PortableCustomDebugInfoKinds.CompilationOptions),
                value: _debugMetadataOpt.GetOrAddBlob(builder));

            void WriteValue(string key, string value)
            {
                builder.WriteUTF8(key);
                builder.WriteByte(0);
                builder.WriteUTF8(value);
                builder.WriteByte(0);
            }
        }
예제 #22
0
파일: BlobTests.cs 프로젝트: rgani/roslyn
        public void GetBlobs()
        {
            var builder = new BlobBuilder(16);
            builder.WriteBytes(1, 100);

            var blobs = builder.GetBlobs().ToArray();
            Assert.Equal(2, blobs.Length);
            Assert.Equal(16, blobs[0].Length);
            Assert.Equal(100 - 16, blobs[1].Length);

            builder.WriteByte(1);

            blobs = builder.GetBlobs().ToArray();
            Assert.Equal(3, blobs.Length);
            Assert.Equal(16, blobs[0].Length);
            Assert.Equal(16, blobs[0].GetUnderlyingBuffer().Array.Length);
            Assert.Equal(100 - 16, blobs[1].Length);
            Assert.Equal(100 - 16, blobs[1].GetUnderlyingBuffer().Array.Length);
            Assert.Equal(1, blobs[2].Length);
            Assert.Equal(100 - 16, blobs[2].GetUnderlyingBuffer().Array.Length);

            builder.Clear();

            blobs = builder.GetBlobs().ToArray();
            Assert.Equal(1, blobs.Length);
            Assert.Equal(0, blobs[0].Length);

            // Clear uses the first buffer:
            Assert.Equal(16, blobs[0].GetUnderlyingBuffer().Array.Length);
        }
        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.CompilationMetadataReferences),
                value: _debugMetadataOpt.GetOrAddBlob(builder));
예제 #24
0
파일: BlobTests.cs 프로젝트: rgani/roslyn
        public void ToImmutableArray()
        {
            var builder = new BlobBuilder(16);

            AssertEx.Equal(new byte[] { }, builder.ToArray(0, 0));

            for (int i = 0; i < 13; i++)
            {
                builder.WriteByte((byte)i);
            }

            builder.WriteUInt32(0xaabbccdd);

            AssertEx.Equal(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0xDD, 0xCC, 0xBB, 0xAA }, builder.ToImmutableArray());
            AssertEx.Equal(new byte[] { }, builder.ToImmutableArray(0, 0));
            AssertEx.Equal(new byte[] { 0 }, builder.ToImmutableArray(0, 1));
            AssertEx.Equal(new byte[] { 1 }, builder.ToImmutableArray(1, 1));

            AssertEx.Equal(new byte[] { }, builder.ToImmutableArray(14, 0));
            AssertEx.Equal(new byte[] { }, builder.ToImmutableArray(15, 0));
            AssertEx.Equal(new byte[] { }, builder.ToImmutableArray(16, 0));
            AssertEx.Equal(new byte[] { }, builder.ToImmutableArray(17, 0));

            AssertEx.Equal(new byte[] { 0xdd }, builder.ToImmutableArray(13, 1));
            AssertEx.Equal(new byte[] { 0xcc }, builder.ToImmutableArray(14, 1));
            AssertEx.Equal(new byte[] { 0xbb }, builder.ToImmutableArray(15, 1));
            AssertEx.Equal(new byte[] { 0xaa }, builder.ToImmutableArray(16, 1));

            AssertEx.Equal(new byte[] { 0xdd, 0xcc }, builder.ToImmutableArray(13, 2));
            AssertEx.Equal(new byte[] { 0xcc, 0xbb }, builder.ToImmutableArray(14, 2));
            AssertEx.Equal(new byte[] { 0xbb, 0xaa }, builder.ToImmutableArray(15, 2));

            AssertEx.Equal(new byte[] { 0xdd, 0xcc, 0xbb }, builder.ToImmutableArray(13, 3));
            AssertEx.Equal(new byte[] { 0xcc, 0xbb, 0xaa }, builder.ToImmutableArray(14, 3));

            AssertEx.Equal(new byte[] { 0xdd, 0xcc, 0xbb, 0xaa }, builder.ToImmutableArray(13, 4));
        }
        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));
        }
예제 #26
0
파일: BlobTests.cs 프로젝트: rgani/roslyn
        public void WriteContentToStream()
        {
            var builder = new BlobBuilder(16);
            for (int i = 0; i < 20; i++)
            {
                builder.WriteByte((byte)i);
            }

            var stream = new MemoryStream();
            builder.WriteContentTo(stream);
            AssertEx.Equal(new byte[]
            {
                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13
            }, stream.ToArray());

            builder.WriteByte(0xff);

            builder.WriteContentTo(stream);
            AssertEx.Equal(new byte[]
            {
                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
                0xff,
            }, stream.ToArray());
        }
        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)));
            }
        }
 /// <summary>
 /// Write string as UTF8 with null terminator.
 /// </summary>
 private static void WriteUtf8String(BlobBuilder builder, string str)
 {
     builder.WriteUTF8(str);
     builder.WriteByte(0);
 }
        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);
        }
예제 #30
0
파일: BlobTests.cs 프로젝트: rgani/roslyn
        public void LinkPrefix1()
        {
            var builder1 = new BlobBuilder(16);
            builder1.WriteByte(1);
            builder1.WriteByte(2);
            builder1.WriteByte(3);

            var builder2 = new BlobBuilder(16);
            builder2.WriteByte(4);

            builder1.LinkPrefix(builder2);

            AssertEx.Equal(new byte[] { 4, 1, 2, 3 }, builder1.ToArray());
        }
        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;
                    }
                }
            }
        }
예제 #32
0
파일: BlobTests.cs 프로젝트: rgani/roslyn
        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());
        }
예제 #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);
 }
예제 #34
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);
        }
예제 #35
0
        private void SerializeTablesHeader(BlobBuilder writer, MetadataSizes metadataSizes)
        {
            int startPosition = writer.Position;

            HeapSizeFlag heapSizes = 0;
            if (metadataSizes.StringIndexSize > 2)
            {
                heapSizes |= HeapSizeFlag.StringHeapLarge;
            }

            if (metadataSizes.GuidIndexSize > 2)
            {
                heapSizes |= HeapSizeFlag.GuidHeapLarge;
            }

            if (metadataSizes.BlobIndexSize > 2)
            {
                heapSizes |= HeapSizeFlag.BlobHeapLarge;
            }

            if (metadataSizes.IsMinimalDelta)
            {
                heapSizes |= (HeapSizeFlag.EnCDeltas | HeapSizeFlag.DeletedMarks);
            }

            ulong sortedDebugTables = metadataSizes.PresentTablesMask & MetadataSizes.SortedDebugTables;

            // Consider filtering out type system tables that are not present:
            ulong sortedTables = sortedDebugTables | (metadataSizes.IsStandaloneDebugMetadata ? 0UL : 0x16003301fa00);

            writer.WriteUInt32(0); // reserved
            writer.WriteByte(MetadataFormatMajorVersion);
            writer.WriteByte(MetadataFormatMinorVersion);
            writer.WriteByte((byte)heapSizes);
            writer.WriteByte(1); // reserved
            writer.WriteUInt64(metadataSizes.PresentTablesMask);
            writer.WriteUInt64(sortedTables);
            SerializeRowCounts(writer, metadataSizes.RowCounts, metadataSizes.PresentTablesMask);

            int endPosition = writer.Position;
            Debug.Assert(metadataSizes.CalculateTableStreamHeaderSize() == endPosition - startPosition);
        }
예제 #36
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);
        }
예제 #37
0
        private void SerializeConstantTable(BlobBuilder writer, MetadataSizes metadataSizes)
        {
            // Note: we can sort the table at this point since no other table can reference its rows via RowId or CodedIndex (which would need updating otherwise).
            var ordered = _constantTableNeedsSorting ? _constantTable.OrderBy((x, y) => (int)x.Parent - (int)y.Parent) : _constantTable;

            foreach (ConstantRow constant in ordered)
            {
                writer.WriteByte(constant.Type);
                writer.WriteByte(0);
                writer.WriteReference(constant.Parent, metadataSizes.HasConstantCodedIndexSize);
                writer.WriteReference((uint)_heaps.ResolveBlobIndex(constant.Value), metadataSizes.BlobIndexSize);
            }
        }
예제 #38
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();
        }
예제 #39
0
        private void SerializeMetadataTables(
            BlobBuilder writer,
            MetadataSizes metadataSizes,
            int methodBodyStreamRva,
            int mappedFieldDataStreamRva)
        {
            int startPosition = writer.Position;

            this.SerializeTablesHeader(writer, metadataSizes);

            if (metadataSizes.IsPresent(TableIndex.Module))
            {
                SerializeModuleTable(writer, metadataSizes, _heaps);
            }

            if (metadataSizes.IsPresent(TableIndex.TypeRef))
            {
                this.SerializeTypeRefTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.TypeDef))
            {
                this.SerializeTypeDefTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.Field))
            {
                this.SerializeFieldTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.MethodDef))
            {
                this.SerializeMethodDefTable(writer, metadataSizes, methodBodyStreamRva);
            }

            if (metadataSizes.IsPresent(TableIndex.Param))
            {
                this.SerializeParamTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.InterfaceImpl))
            {
                this.SerializeInterfaceImplTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.MemberRef))
            {
                this.SerializeMemberRefTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.Constant))
            {
                this.SerializeConstantTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.CustomAttribute))
            {
                this.SerializeCustomAttributeTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.FieldMarshal))
            {
                this.SerializeFieldMarshalTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.DeclSecurity))
            {
                this.SerializeDeclSecurityTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.ClassLayout))
            {
                this.SerializeClassLayoutTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.FieldLayout))
            {
                this.SerializeFieldLayoutTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.StandAloneSig))
            {
                this.SerializeStandAloneSigTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.EventMap))
            {
                this.SerializeEventMapTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.Event))
            {
                this.SerializeEventTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.PropertyMap))
            {
                this.SerializePropertyMapTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.Property))
            {
                this.SerializePropertyTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.MethodSemantics))
            {
                this.SerializeMethodSemanticsTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.MethodImpl))
            {
                this.SerializeMethodImplTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.ModuleRef))
            {
                this.SerializeModuleRefTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.TypeSpec))
            {
                this.SerializeTypeSpecTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.ImplMap))
            {
                this.SerializeImplMapTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.FieldRva))
            {
                this.SerializeFieldRvaTable(writer, metadataSizes, mappedFieldDataStreamRva);
            }

            if (metadataSizes.IsPresent(TableIndex.EncLog))
            {
                this.SerializeEncLogTable(writer);
            }

            if (metadataSizes.IsPresent(TableIndex.EncMap))
            {
                this.SerializeEncMapTable(writer);
            }

            if (metadataSizes.IsPresent(TableIndex.Assembly))
            {
                this.SerializeAssemblyTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.AssemblyRef))
            {
                this.SerializeAssemblyRefTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.File))
            {
                this.SerializeFileTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.ExportedType))
            {
                this.SerializeExportedTypeTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.ManifestResource))
            {
                this.SerializeManifestResourceTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.NestedClass))
            {
                this.SerializeNestedClassTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.GenericParam))
            {
                this.SerializeGenericParamTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.MethodSpec))
            {
                this.SerializeMethodSpecTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.GenericParamConstraint))
            {
                this.SerializeGenericParamConstraintTable(writer, metadataSizes);
            }

            // debug tables
            if (metadataSizes.IsPresent(TableIndex.Document))
            {
                this.SerializeDocumentTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.MethodDebugInformation))
            {
                this.SerializeMethodDebugInformationTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.LocalScope))
            {
                this.SerializeLocalScopeTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.LocalVariable))
            {
                this.SerializeLocalVariableTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.LocalConstant))
            {
                this.SerializeLocalConstantTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.ImportScope))
            {
                this.SerializeImportScopeTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.StateMachineMethod))
            {
                this.SerializeStateMachineMethodTable(writer, metadataSizes);
            }

            if (metadataSizes.IsPresent(TableIndex.CustomDebugInformation))
            {
                this.SerializeCustomDebugInformationTable(writer, metadataSizes);
            }

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

            int endPosition = writer.Position;
            Debug.Assert(metadataSizes.MetadataTableStreamSize == endPosition - startPosition);
        }
예제 #40
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;
                    }
                }
            }
        }
예제 #41
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)
            {
                if (local.IsDynamic)
                {
                    dynamicLocals.Add(local);
                }
            }

            int dynamicVariableCount = dynamicLocals.Count;

            foreach (var currentScope in methodBody.LocalScopes)
            {
                foreach (var localConstant in currentScope.Constants)
                {
                    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 blobSize = 200;          //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);

            int localIndex = 0;

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

                var dynamicTransformFlags = local.DynamicTransformFlags;
                if (!dynamicTransformFlags.IsDefault && dynamicTransformFlags.Length <= 64)
                {
                    byte[] flag = new byte[64];
                    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, 68); //Empty flag array and size.
                }

                if (localIndex < dynamicVariableCount)
                {
                    // Dynamic variable
                    cmw.WriteUInt32((uint)local.SlotIndex);
                }
                else
                {
                    // Dynamic constant
                    cmw.WriteUInt32(0);
                }

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

                localIndex++;
            }

            dynamicLocals.Free();
            customDebugInfo.Add(cmw);
        }