Esempio n. 1
0
        private static PooledBlobBuilder SerializeRecord(
            byte kind,
            EditAndContinueMethodDebugInformation debugInfo,
            Action <EditAndContinueMethodDebugInformation, BlobBuilder> recordSerializer)
        {
            var cmw = PooledBlobBuilder.GetInstance();

            cmw.WriteByte(CDI.CdiVersion);
            cmw.WriteByte(kind);
            cmw.WriteByte(0);

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

            recordSerializer(debugInfo, cmw);

            int  length        = cmw.Count;
            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);
        }
        public byte[] SerializeMethodDebugInfo(EmitContext context, IMethodBody methodBody, MethodDefinitionHandle methodHandle, bool emitEncInfo, bool suppressNewCustomDebugInfo, out bool emitExternNamespaces)
        {
            emitExternNamespaces = false;

            // CONSIDER: this may not be the same "first" method as in Dev10, but
            // it shouldn't matter since all methods will still forward to a method
            // containing the appropriate information.
            if (_methodBodyWithModuleInfo == null)
            {
                // This module level information could go on every method (and does in
                // the edit-and-continue case), but - as an optimization - we'll just
                // put it on the first method we happen to encounter and then put a
                // reference to the first method's token in every other method (so they
                // can find the information).
                if (context.Module.GetAssemblyReferenceAliases(context).Any())
                {
                    _methodWithModuleInfo     = methodHandle;
                    _methodBodyWithModuleInfo = methodBody;
                    emitExternNamespaces      = true;
                }
            }

            var pooledBuilder = PooledBlobBuilder.GetInstance();
            var encoder       = new CustomDebugInfoEncoder(pooledBuilder);

            // NOTE: This is an attempt to match Dev10's apparent behavior.  For iterator methods (i.e. the method
            // that appears in source, not the synthesized ones), Dev10 only emits the StateMachineTypeName
            // custom debug info (e.g. there will be no information about the usings that were in scope).
            // NOTE: There seems to be an unusual behavior in ISymUnmanagedWriter where, if all the methods in a type are
            // iterator methods, no custom debug info is emitted for any method.  Adding a single non-iterator
            // method causes the custom debug info to be produced for all methods (including the iterator methods).
            // Since we are making the same ISymUnmanagedWriter calls as Dev10, we see the same behavior (i.e. this
            // is not a regression).
            if (methodBody.StateMachineTypeName != null)
            {
                encoder.AddStateMachineTypeName(methodBody.StateMachineTypeName);
            }
            else
            {
                SerializeNamespaceScopeMetadata(ref encoder, context, methodBody);

                encoder.AddStateMachineHoistedLocalScopes(methodBody.StateMachineHoistedLocalScopes);
            }

            if (!suppressNewCustomDebugInfo)
            {
                SerializeDynamicLocalInfo(ref encoder, methodBody);
                SerializeTupleElementNames(ref encoder, methodBody);

                if (emitEncInfo)
                {
                    var encMethodInfo = MetadataWriter.GetEncMethodDebugInfo(methodBody);
                    SerializeCustomDebugInformation(ref encoder, encMethodInfo);
                }
            }

            byte[] result = encoder.ToArray();
            pooledBuilder.Free();
            return(result);
        }
Esempio n. 3
0
        private static void SerializeStateMachineLocalScopes(IMethodBody methodBody, ArrayBuilder <PooledBlobBuilder> customDebugInfo)
        {
            var scopes = methodBody.StateMachineHoistedLocalScopes;

            if (scopes.IsDefaultOrEmpty)
            {
                return;
            }

            uint numberOfScopes = (uint)scopes.Length;
            var  cmw            = PooledBlobBuilder.GetInstance();

            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);
        }
Esempio n. 4
0
        private static PooledBlobBuilder SerializeRecord <T>(
            CustomDebugInfoKind kind,
            T debugInfo,
            Action <T, BlobBuilder> recordSerializer)
        {
            PooledBlobBuilder cmw = PooledBlobBuilder.GetInstance();

            cmw.WriteByte(CustomDebugInfoConstants.Version);
            cmw.WriteByte((byte)kind);
            cmw.WriteByte(0);

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

            recordSerializer(debugInfo, cmw);

            int  length        = cmw.Count;
            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);
        }
Esempio n. 5
0
        private static PooledBlobBuilder SerializeRecord(byte kind, Action <BlobBuilder> data)
        {
            var cmw = PooledBlobBuilder.GetInstance();

            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);
        }
Esempio n. 6
0
        private void SerializeReferenceToPreviousMethodWithUsingInfo(ArrayBuilder <PooledBlobBuilder> customDebugInfo)
        {
            var cmw = PooledBlobBuilder.GetInstance(12);

            cmw.WriteByte(CDI.CdiVersion);
            cmw.WriteByte(CDI.CdiKindForwardInfo);
            cmw.Align(4);
            cmw.WriteUInt32(12);
            cmw.WriteUInt32((uint)_previousMethodTokenWithUsingInfo);
            customDebugInfo.Add(cmw);
        }
Esempio n. 7
0
        private void SerializeReferenceToMethodWithModuleInfo(ArrayBuilder <PooledBlobBuilder> customDebugInfo)
        {
            PooledBlobBuilder cmw = PooledBlobBuilder.GetInstance();

            cmw.WriteByte(CustomDebugInfoConstants.Version);
            cmw.WriteByte((byte)CustomDebugInfoKind.ForwardToModuleInfo);
            cmw.Align(4);
            cmw.WriteUInt32(12);
            cmw.WriteUInt32((uint)_methodTokenWithModuleInfo);
            customDebugInfo.Add(cmw);
        }
Esempio n. 8
0
        public byte[] SerializeMethodDebugInfo(EmitContext context, IMethodBody methodBody, MethodDefinitionHandle methodHandle, bool emitEncInfo, bool suppressNewCustomDebugInfo, out bool emitExternNamespaces)
        {
            emitExternNamespaces = false;

            // CONSIDER: this may not be the same "first" method as in Dev10, but
            // it shouldn't matter since all methods will still forward to a method
            // containing the appropriate information.
            if (_methodBodyWithModuleInfo == null)
            {
                // This module level information could go on every method (and does in
                // the edit-and-continue case), but - as an optimization - we'll just
                // put it on the first method we happen to encounter and then put a
                // reference to the first method's token in every other method (so they
                // can find the information).
                if (context.Module.GetAssemblyReferenceAliases(context).Any())
                {
                    _methodWithModuleInfo     = methodHandle;
                    _methodBodyWithModuleInfo = methodBody;
                    emitExternNamespaces      = true;
                }
            }

            var pooledBuilder = PooledBlobBuilder.GetInstance();
            var encoder       = new CustomDebugInfoEncoder(pooledBuilder);

            if (methodBody.StateMachineTypeName != null)
            {
                encoder.AddStateMachineTypeName(methodBody.StateMachineTypeName);
            }
            else
            {
                SerializeNamespaceScopeMetadata(ref encoder, context, methodBody);

                encoder.AddStateMachineHoistedLocalScopes(methodBody.StateMachineHoistedLocalScopes);
            }

            if (!suppressNewCustomDebugInfo)
            {
                SerializeDynamicLocalInfo(ref encoder, methodBody);
                SerializeTupleElementNames(ref encoder, methodBody);

                if (emitEncInfo)
                {
                    var encMethodInfo = MetadataWriter.GetEncMethodDebugInfo(methodBody);
                    SerializeCustomDebugInformation(ref encoder, encMethodInfo);
                }
            }

            byte[] result = encoder.ToArray();
            pooledBuilder.Free();
            return(result);
        }
Esempio n. 9
0
 internal PdbLogger(bool logging)
 {
     _logging = logging;
     if (logging)
     {
         _logData = PooledBlobBuilder.GetInstance();
         _hashAlgorithm = new SHA1CryptoServiceProvider();
         Debug.Assert(_hashAlgorithm.SupportsTransform);
     }
     else
     {
         _logData = null;
         _hashAlgorithm = null;
     }
 }
Esempio n. 10
0
        private void SerializeNamespaceScopeMetadata(EmitContext context, IMethodBody methodBody, ArrayBuilder <PooledBlobBuilder> 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         = PooledBlobBuilder.GetInstance();

            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.Count);
                customDebugInfo.Add(cmw);
            }

            if (_methodBodyWithModuleInfo != null && !ReferenceEquals(_methodBodyWithModuleInfo, methodBody))
            {
                SerializeReferenceToMethodWithModuleInfo(customDebugInfo);
            }
        }
Esempio n. 11
0
        public BlobIdx GetConstantBlobIndex(object value)
        {
            string str = value as string;

            if (str != null)
            {
                return(this.GetBlobIndex(str));
            }

            var writer = PooledBlobBuilder.GetInstance();

            writer.WriteConstant(value);
            var result = this.GetBlobIndex(writer);

            writer.Free();
            return(result);
        }
Esempio n. 12
0
        private static void SerializeReferenceToIteratorClass(string iteratorClassName, ArrayBuilder <PooledBlobBuilder> customDebugInfo)
        {
            if (iteratorClassName == null)
            {
                return;
            }
            PooledBlobBuilder cmw = PooledBlobBuilder.GetInstance();

            cmw.WriteByte(CustomDebugInfoConstants.Version);
            cmw.WriteByte((byte)CustomDebugInfoKind.ForwardIterator);
            cmw.Align(4);
            uint length = 10 + (uint)iteratorClassName.Length * 2;

            if ((length & 3) != 0)
            {
                length += 4 - (length & 3);
            }
            cmw.WriteUInt32(length);
            WriteUtf16String(cmw, iteratorClassName);
            cmw.Align(4);
            Debug.Assert(cmw.Count == length);
            customDebugInfo.Add(cmw);
        }
Esempio n. 13
0
        private static void SerializeReferenceToIteratorClass(string iteratorClassName, ArrayBuilder <PooledBlobBuilder> customDebugInfo)
        {
            if (iteratorClassName == null)
            {
                return;
            }
            var cmw = PooledBlobBuilder.GetInstance();

            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);
        }
Esempio n. 14
0
        private static void SerializeDynamicLocalInfo(IMethodBody methodBody, ArrayBuilder <PooledBlobBuilder> 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 = PooledBlobBuilder.GetInstance();

            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);
        }
Esempio n. 15
0
        private static void SerializeDynamicLocalInfo(IMethodBody methodBody, ArrayBuilder <PooledBlobBuilder> customDebugInfo)
        {
            if (!methodBody.HasDynamicLocalVariables)
            {
                return; //There are no dynamic locals
            }

            const int dynamicAttributeSize = 64;
            const int identifierSize       = 64;

            ArrayBuilder <ILocalDefinition> dynamicLocals = GetLocalInfoToSerialize(
                methodBody,
                local =>
            {
                System.Collections.Immutable.ImmutableArray <TypedConstant> dynamicTransformFlags = local.DynamicTransformFlags;
                return(!dynamicTransformFlags.IsEmpty &&
                       dynamicTransformFlags.Length <= dynamicAttributeSize &&
                       local.Name.Length < identifierSize);
            },
                (scope, local) => local);

            if (dynamicLocals == null)
            {
                return;
            }

            const int         blobSize = dynamicAttributeSize + 4 + 4 + identifierSize * 2;//DynamicAttribute: 64, DynamicAttributeLength: 4, SlotIndex: 4, IdentifierName: 128
            PooledBlobBuilder cmw      = PooledBlobBuilder.GetInstance();

            cmw.WriteByte(CustomDebugInfoConstants.Version);
            cmw.WriteByte((byte)CustomDebugInfoKind.DynamicLocals);
            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)
            {
                System.Collections.Immutable.ImmutableArray <TypedConstant> dynamicTransformFlags = local.DynamicTransformFlags;
                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

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